目录
一、概述
监听器:专门用于对域对象对象身上发生的事件或状态改变进行监听和相应处理的对象
监听器是GOF设计模式中,观察者模式的典型案例
观察者模式: 当被观察的对象发生某些改变时, 观察者自动采取对应的行动的一种设计模式
监听器使用的感受类似JS中的事件,被观察的对象发生某些情况时,自动触发代码的执行
监听器并不监听web项目中的所有组件,仅仅是对三大域对象做相关的事件监听
二、分类
按监听的对象划分
application域监听器 ServletContextListener ServletContextAttributeListener
session域监听器 HttpSessionListener HttpSessionAttributeListener HttpSessionBindingListener HttpSessionActivationListener
request域监听器 ServletRequestListener ServletRequestAttributeListener
按监听的事件分
域对象的创建和销毁监听器 ServletContextListener HttpSessionListener ServletRequestListener
域对象数据增删改事件监听器 ServletContextAttributeListener HttpSessionAttributeListener ServletRequestAttributeListener
其他监听器 HttpSessionBindingListener HttpSessionActivationListener
三、监听器的六个主要接口
下面这6个:
域对象的创建和销毁监听器 ServletContextListener HttpSessionListener ServletRequestListener
域对象数据增删改事件监听器 ServletContextAttributeListener HttpSessionAttributeListener ServletRequestAttributeListener
下面以应用域的监听器为例
application域监听器
(1)两个接口和API
ServletContextListener 监听ServletContext对象的创建与销毁
ServletContextEvent对象代表从ServletContext对象身上捕获到的事件,通过这个事件对象我们可以获取到ServletContext对象。
方法名 作用 contextInitialized(ServletContextEvent sce) ServletContext创建时调用 contextDestroyed(ServletContextEvent sce) ServletContext销毁时调用
ServletContextAttributeListener 监听ServletContext中属性的添加、移除和修改
方法名 作用 attributeAdded(ServletContextAttributeEvent scab) 向ServletContext中添加属性时调用 attributeRemoved(ServletContextAttributeEvent scab) 从ServletContext中移除属性时调用 attributeReplaced(ServletContextAttributeEvent scab) 当ServletContext中的属性被修改时调用 ServletContextAttributeEvent对象代表属性变化事件,它包含的方法如下:
方法名 作用 getName() 获取修改或添加的属性名 getValue() 获取被修改或添加的属性值 getServletContext() 获取ServletContext对象
(2)使用
定义监听器(要使用@WebListener注解才起作用)
@WebListener public class ApplicationListener implements ServletContextListener , ServletContextAttributeListener { // 监听初始化 @Override public void contextInitialized(ServletContextEvent sce) { ServletContext application = sce.getServletContext(); System.out.println("application"+application.hashCode()+" initialized"); } // 监听销毁 @Override public void contextDestroyed(ServletContextEvent sce) { ServletContext application = sce.getServletContext(); System.out.println("application"+application.hashCode()+" destroyed"); } // 监听数据增加 @Override public void attributeAdded(ServletContextAttributeEvent scae) { String name = scae.getName(); Object value = scae.getValue(); ServletContext application = scae.getServletContext(); System.out.println("application"+application.hashCode()+" add:"+name+"="+value); } // 监听数据移除 @Override public void attributeRemoved(ServletContextAttributeEvent scae) { String name = scae.getName(); Object value = scae.getValue(); ServletContext application = scae.getServletContext(); System.out.println("application"+application.hashCode()+" remove:"+name+"="+value); } // 监听数据修改 @Override public void attributeReplaced(ServletContextAttributeEvent scae) { String name = scae.getName(); Object value = scae.getValue(); ServletContext application = scae.getServletContext(); Object newValue = application.getAttribute(name); System.out.println("application"+application.hashCode()+" change:"+name+"="+value+" to "+newValue); } }
定义触发监听器的代码
// ServletA用于向application域中放入数据 @WebServlet(urlPatterns = "/servletA",name = "servletAName") public class ServletA extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 向application域中放入数据 ServletContext application = this.getServletContext(); application.setAttribute("k1","v1"); application.setAttribute("k2","v2"); } } // ServletB用于向application域中修改和移除数据 @WebServlet(urlPatterns = "/servletB", name = "servletBName") public class ServletB extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext appliation = getServletContext(); // 修改application域中的数据 appliation.setAttribute("k1","value1"); // 删除application域中的数据 appliation.removeAttribute("k2"); } }
四、session域的两个特殊监听器(少用)
就是监听器的监听器
这两个监听器不是用注解@WebListener激活的,而是在Servlet代码中引用的。
1.session绑定监听器
(1)接口API和参数对象的API
HttpSessionBindingListener 监听当前监听器对象在Session域中的增加与移除
方法名 作用 valueBound(HttpSessionBindingEvent event) 该类的实例被放到Session域中时调用 valueUnbound(HttpSessionBindingEvent event) 该类的实例从Session中移除时调用 HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:
方法名 作用 getName() 获取当前事件涉及的属性名 getValue() 获取当前事件涉及的属性值 getSession() 获取触发事件的HttpSession对象
(2)使用
定义监听器 (不用加注解)
public class MySessionBindingListener implements HttpSessionBindingListener { // 监听绑定 @Override public void valueBound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); String name = event.getName(); System.out.println("MySessionBindingListener"+this.hashCode()+" binding into session"+session.hashCode()+" with name "+name); } // 监听解除绑定 @Override public void valueUnbound(HttpSessionBindingEvent event) { HttpSession session = event.getSession(); String name = event.getName(); System.out.println("MySessionBindingListener"+this.hashCode()+" unbond outof session"+session.hashCode()+" with name "+name); } }
定义触发监听器的代码
把监听器当数据存
@WebServlet(urlPatterns = "/servletA",name = "servletAName") public class ServletA extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); // 绑定监听器 session.setAttribute("bindingListener",new MySessionBindingListener()); // 解除绑定监听器 session.removeAttribute("bindingListener"); } }
2.钝化活化监听器
就是将web项目的会话域对象存到磁盘和取出磁盘
(1)接口API和参数对象的API
HttpSessionActivationListener 监听某个对象在Session中的序列化与反序列化。
方法名 作用 sessionWillPassivate(HttpSessionEvent se) 该类实例和Session一起钝化到硬盘时调用 sessionDidActivate(HttpSessionEvent se) 该类实例和Session一起活化到内存时调用 HttpSessionEvent对象代表事件对象,通过getSession()方法获取事件涉及的HttpSession对象。
(2)什么是钝化
session对象在服务端是以对象的形式存储于内存的,session过多,服务器的内存也是吃不消的
而且一旦服务器发生重启,所有的session对象都将被清除,也就意味着session中存储的不同客户端的登录状态丢失
为了分摊内存 压力并且为了保证session重启不丢失,我们可以设置将session进行钝化处理
在关闭服务器前或者到达了设定时间时,对session进行序列化到磁盘,这种情况叫做session的钝化
在服务器启动后或者再次获取某个session时,将磁盘上的session进行反序列化到内存,这种情况叫做session的活化
(3)如何配置钝化活化
A.在web目录下,添加 META-INF下创建Context.xml
B.Context.xml中配置钝化
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="d:\mysession"></Store>
</Manager>
</Context>
C.请求servletA,获得session,并存入数据,然后重启服务器
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
// 添加数据
session.setAttribute("k1","v1");
}
}
D.请求servletB获取session,获取重启前存入的数据
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Object v1 = session.getAttribute("k1");
System.out.println(v1);
}
}
(4)监听钝化活化
定义监听器
涉及序列化,要实现Serializable接口
public class ActivationListener implements HttpSessionActivationListener, Serializable { // 监听钝化 @Override public void sessionWillPassivate(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("session with JSESSIONID "+ session.getId()+" will passivate"); } // 监听活化 @Override public void sessionDidActivate(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("session with JSESSIONID "+ session.getId()+" did activate"); } }
定义触发监听器的代码
当数据存就行
@WebServlet(urlPatterns = "/servletA",name = "servletAName") public class ServletA extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); // 添加数据 session.setAttribute("k1","v1"); // 添加钝化活化监听器 session.setAttribute("activationListener",new ActivationListener()); } }