Servlet事件监听器
什么是监听器?
监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
事件源就是被监听对象,本身是一个java对象;
事件源产生事件,传给事件监听器进行处理,原因:事件监听器对象实现在事件源里进行注册;
Servle监听器
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为 ServletContext, HttpSession 和 ServletRequest 这三个域对象。
Servlet规范针对这三个对象上的操作,又把这多种类型的监听器划分为三种类型。
监听三个域对象创建和销毁的事件监听器
监听域对象中属性的增加和删除的事件监听器
监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。(查看API文档)
监听servletContext域对象创建和销毁
ServletContextListener 接口用于监听 ServletContext 对象的创建和销毁事件。
当 ServletContext 对象被创建时,激发contextInitialized (ServletContextEvent sce)方法
当 ServletContext 对象被销毁时,激发contextDestroyed(ServletContextEvent sce)方法。
创建:服务器启动针对每一个web应用创建servletcontext
销毁:服务器关闭前先关闭代表每一个web应用的servletContext
编写 Servlet 监听器
和编写其它事件监听器一样,编写servlet监听器也需要实现一个特定的接口,并针对相应动作覆盖接口中的相应方法。
和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动把监听器注册到事件源中。
一个 web.xml 文件中可以配置多个 Servlet 事件监听器,web 服务器按照它们在 web.xml 文件中的注册顺序来加载和注册这些 Serlvet 事件监听器。
监听HttpSession域对象创建和销毁
HttpSessionListener接口用于监听HttpSession创建和销毁
创建一个Session时,sessionCreated(HttpSessionEvent se) 方法将会被调用。
销毁一个Session时,sessionDestroyed (HttpSessionEvent se) 方法将会被调用。
Session域对象创建和销毁的时机
创建:用户每一次访问时,服务器创建session
销毁:如果用户的session 30分钟没有使用,服务器就会销毁session,我们在web.xml里面也可以配置session失效时间
监听HttpRequest域对象创建和销毁
ServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。
Request 对象被创建时,监听器的requestInitialized方法将会被调用。
Request对象被销毁时,监听器的requestDestroyed方法将会被调用。
(此处复习request对象,在浏览器窗口中多次刷新访问servlet,看request对象的创建和销毁,并写一个servlet,然后用sendRedirect、forward方式跳转到其它servlet,查看request对象的创建和消耗)
servletRequest域对象创建和销毁的时机:
创建:用户每一次访问,都会创建一个reqeust
销毁:当前访问结束,request对象就会销毁
Servlet监听器在开发中的应用案例:
统计当前在线人数
public class CreateSession implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer count = (Integer) context.getAttribute("count");
if(count==null){
count = 1;
context.setAttribute("count", count);
}else{
count++;
context.setAttribute("count", count);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext context = se.getSession().getServletContext();
Integer count = (Integer) context.getAttribute("count");
count--;
context.setAttribute("count", count);
}
}
监听三个域对象属性变化
Servlet规范定义了监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信息事件的监听器。
这三个监听器接口分别是ServletContextAttributeListener, HttpSessionAttributeListener ServletRequestAttributeListener
这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。
attributeAdded 方法
当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象
各个域属性监听器中的完整语法定义为:
public void attributeAdded(ServletContextAttributeEvent scae)
public void attributeAdded(HttpSessionBindingEvent hsbe)
public void attributeAdded(ServletRequestAttributeEvent srae)
根据监听的域对象不一样,穿过来的参数选择不同方法;
attributeRemoved 方法
当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行相应
各个域属性监听器中的完整语法定义为:
public void attributeRemoved(ServletContextAttributeEvent scae)
public void attributeRemoved (HttpSessionBindingEvent hsbe)
public void attributeRemoved (ServletRequestAttributeEvent srae)
attributeReplaced 方法
当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应
各个域属性监听器中的完整语法定义为:
public void attributeReplaced(ServletContextAttributeEvent scae)
public void attributeReplaced (HttpSessionBindingEvent hsbe)
public void attributeReplaced (ServletRequestAttributeEvent srae)
首先一个domain类,在这里就不连接数据库了,
然后进入正题,编写一个servlet类,RemoveServlet作用:来了一个用户名密码获取到,传到服务类里,调dao里的方法是否与数据库里的值相等,返回一个user对象;
1、获取登陆页的密码和用户名
2、New一个user,并给他赋值,
3、把用户放到session里,//给session添加了属性
4、重定向到index.jsp;(因为没有连接数据库,所以省略了很多
接下来写监听器监听用户:
1、实现HttpSessionAttributeListener接口;实现其方法
2、获取下添加的值,即用户名的值,属于User类型返回一个obj
3、判断obj是否是User类型,是的话把obj强转成user类型;
4、获取Session返回一个HttpSession,通过Session获取上下文的属性集合;集合用map表示,因为他有键值;用list不好,因为接下来要记住用户属于哪一个Session;返回一个Map,
5、判断map==null的话,创建new一个集合HashMap();把map放到上下文属性里面;
6、如果不为空,直接把user放到map里,map.put(user.getUsername,session);
这样监听就做完了,需要注册一下,在web.xml文件里;
创建一个jsp,用户列表;
1、用c:forEach,遍历为items和var赋值
2、获取map的值,
3、写一个连接,踢出用户:<a href = “Servlet类,?username=${me.key}”>踢出</a>
创建一个踢出的Servlet类
步骤:把Session销毁,再从map里取出;
1、获取username
2、获取上下文的属性map,返回一个map
3、获取map里的username属性,返回一个Session
4、如果Session不为空,销毁session,用invalidate();
在map里删除;
5、最后转发到用户列表的jsp文件
然后需要加一下过滤器,编一下码,否则中文有乱码,也踢出不掉;
然后再用户显示列表中优化一下
在forEach里面<c:url>设置一下value值,
在子标签里加一个属性,获取map的key值
最后还需要在踢出的servlet类里为username 设置一下编码;
username = new String(username . getBytes(“iso8859-1”),”utf-8”);