一、监听三个域对象创建和销毁的事件监听器
1. ServletContextListener接口
MyServletContextListener:
public class MyServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println(arg0.getServletContext()+"被销毁了");
}
public void contextInitialized(ServletContextEvent arg0) {
System.out.println(arg0.getServletContext()+"被创建了");
}
Web.xml
<listener>
<listener-class>cn.class3g.web.listener.MyServletContextListener</listener-class>
</listener>
应用:在web服务的启动时提供或创建资源,结束时回收。如web应用启动时利用ServletContextListener将数据表和数据准备好,则将创建表和数据的代码写在其中。Spring框架就是以监听器的形式启动的。
问如果有多个监听器,在web.xml中注册时,怎样判断监听器的监听对象?
答:利用java的反射机制
If(Object instanceOf ServletContextListener){
}else if(Object instanceOf HttpSessionListener{
}
2. HttpSessionListener接口
MySessionListener
书写语句同上
HttpSessionListener的作用:统计在线人数
3. ServletRequestListener接口
MyServletRequestListener
案例:统计当前在线人数
OnlineListener
public class OnlineListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent se) {
ServletContext context=se.getSession().getServletContext();
Integer count=(Integer)context.getAttribute("peopleOnline");
if(count==null){//如果是第一个用户ServletContext域中创建属性,并且赋值为1
count=1;
}else{
count++;
}
context.setAttribute("peopleOnline",count);
}
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context=se.getSession().getServletContext();
Integer count=(Integer)context.getAttribute("peopleOnline");
count--;
context.setAttribute("peopleOnline",count);
}
Index.jsp
<body>
当前在线人数为:${applicationScope.peopleOnline}
</body>
二、监听三个域对象属性变化
1. ServletContextAttributeListener接口
MyServletContextAttributeListener
public class MyServletContextAttributeListener implements
ServletContextAttributeListener {
public void attributeAdded(ServletContextAttributeEvent arg0) {
ServletContext context=arg0.getServletContext();
Object obj=arg0.getValue();//属性值
System.out.println(context+"加入了"+obj);
}
public void attributeRemoved(ServletContextAttributeEvent arg0) {
ServletContext context=arg0.getServletContext();
Object obj=arg0.getValue();//属性值
System.out.println(context+"删除了"+obj);
}
public void attributeReplaced(ServletContextAttributeEvent arg0) {
ServletContext context=arg0.getServletContext();
Object obj=arg0.getValue();//属性值
System.out.println(context+"修改了"+obj);
}
2. HttpSessionAttributeListener接口
3. ServletRequestAttributeListener接口
三、感知 Session 绑定的事件监听器
保存在 Session 域中的对象可以有多种状态:
绑定到 Session 中;从 Session 域中解除绑定;
随 Session 对象持久化到一个存储设备中;
随 Session 对象从一个存储设备中恢复
Servlet 规范中定义了两个特殊的监听器接口来帮助 JavaBean 对象了解自己在 Session 域中的这些状态:HttpSessionBindingListener接口和HttpSessionActivationListener接口 ,实现这两个接口的类不需要 web.xml 文件中进行注册
注:监听自己——>不需要注册
事件源是自己
1. HttpSessionBindingListener接口
实现了HttpSessionBindingListener接口的 JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件
User
//User对象能够监视自己在session中的绑定状态
//自己监视自己,无需注册
//可以用来统计在线用户(即登录用户),注意区分与在线人数的区别
public class User implements HttpSessionBindingListener{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println("我被绑定到session中了");
}
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println("我被从session中删除了");
}
实际用途:
统计网站在线人数
1. HttpSessionActivationListener接口
实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件
四、显示登陆用户列表,并实现踢人功能
用户:login.jsp à loginServlet à index.jsp
管理员: listUser.jsp à kickUserServlet
监听器:SessionAttributeListener
Bean: User
cn.class.domain.User
public class User {
private String username;
private String password;
public User(String username, String password) {
super();
this.username = username;
this.password = password;
}
public User() {
super();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
login.jsp
<body>
<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
cn.class3g.web.servlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username=request.getParameter("username");
String password=request.getParameter("password");
User user=new User(username,password);
request.getSession().setAttribute("user",user);
//用重定向,不用再转发
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
index.jsp
<body>
欢迎您:${user.username }
</body>
cn.class3g.web.listener
public class SessionAttributeListener implements HttpSessionAttributeListener {
public void attributeAdded(HttpSessionBindingEvent arg0) {
Object obj=arg0.getValue();
if(obj instanceof User){
HttpSession session=arg0.getSession();
ServletContext context=session.getServletContext();
Map map=(Map)session.getServletContext().getAttribute("map");
if(map==null){//第一个用户登录,此时还没有创建Map集合
map=new HashMap();
context.setAttribute("map",map);
}
User user=(User)obj;
//登录用户的用户名作为key,登录用户的session对象作为value
map.put(user.getUsername(), session);
}
}
public void attributeRemoved(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
public void attributeReplaced(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
}
}
listUser.jsp
<body>
当前的登录用户有:<br/>
<c:forEach var="me" items="${map}">
${me.key }
<a href="${pageContext.request.contextPath}/servlet/KickUserServlet?username=${me.key}">
踢死你!
</a><br/><br/>
</c:forEach>
</body>
cn.class3g.web.servlet
public class KickUserServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username=request.getParameter("username");
Map map=(Map) this.getServletContext().getAttribute("map");
HttpSession session=(HttpSession) map.get(username);
if(session!=null){//开踢
session.invalidate();
map.remove(username);
}
request.getRequestDispatcher("/listUser.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
测试流程:
1. 模仿用户登录(多个)
2. 模仿管理员访问listUser.jsp ,踢人
3. 用户重新刷新index.jsp ,发现session已被销毁