文章目录
- 一、监听器是什么
- 二、监听器的分类
- 三、监听器的六个主要接口
- 3.1 application域监听器
- 测试代码 :
- 3.1.1 定义监听器
- 3.1.2 定义触发监听器的代码
- 3.2 session域监听器
- 测试代码 :
- 3.2.1 定义监听器
- 3.2.2 定义触发监听器的代码
- 3.3 request域监听器
- 测试代码:
- 3.3.1 定义监听器
- 3.3.2 定义触发监听器的代码
- 3.4 session域的两个特殊监听器
- 3.4.1 session绑定监听器
- 测试代码:
- 3.4.2 定义监听器
- 3.4.3 定义监听器
- 3.5 钝化活化监听器(序列化与反序列化
- 如何配置钝化活化
- 如何监听钝化活化
- 总结
一、监听器是什么
-
类似 JS 的事件
- 被观察的对象发生某些情况时,自动触发代码的执行
-
对域对象要发生的方法进行监听
-
并不监听web项目中的所有组件,仅仅是对三大域对象做相关的事件监听
-
监听器是GOF设计模式中,观察者模式的典型案例
- 观察者模式: 当被观察的对象发生某些改变时, 观察者自动采取对应的行动的一种设计模式
二、监听器的分类
web中定义八个监听器接口作为监听器的规范,
这八个接口按照不同的标准可以形成不同的分类 :
-
按监听的对象划分
- application域监听器
ServletContextListener
ServletContextAttributeListener
- session域监听器
HttpSessionListener
HttpSessionAttributeListener
HttpSessionBindingListener
HttpSessionActivationListener
- request域监听器
ServletRequestListener
ServletRequestAttributeListener
- application域监听器
-
按监听的事件分
- 域对象的创建和销毁监听器
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
- 域对象数据增删改事件监听器
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletRequestAttributeListener
- 其他监听器
- HttpSessionBindingListener
- HttpSessionActivationListener
- 域对象的创建和销毁监听器
三、监听器的六个主要接口
3.1 application域监听器
ServletContextListener
监听ServletContext对象的创建与销毁
方法名 | 作用 |
---|---|
contextInitialized(ServletContextEvent sce) | ServletContext创建时调用 |
contextDestroyed(ServletContextEvent sce) | ServletContext销毁时调用 |
- ServletContextEvent对象代表从ServletContext对象身上捕获到的事件,
- 通过这个事件对象我们可以获取到ServletContext对象。
ServletContextAttributeListener
监听ServletContext中属性的添加、移除和修改
方法名 | 作用 |
---|---|
attributeAdded(ServletContextAttributeEvent scab) | 向ServletContext中添加属性时调用 |
attributeRemoved(ServletContextAttributeEvent scab) | 从ServletContext中移除属性时调用 |
attributeReplaced(ServletContextAttributeEvent scab) | 当ServletContext中的属性被修改时调用 |
ServletContextAttributeEvent
对象代表属性变化事件,它包含的方法如下:
方法名 | 作用 |
---|---|
getName() | 获取修改或添加的属性名 |
getValue() | 获取被修改或添加的属性值 |
getServletContext() | 获取ServletContext对象 |
测试代码 :
3.1.1 定义监听器
@WebListener
public class ApplicationListener implements ServletContextListener , ServletContextAttributeListener {// 监听初始化@Overridepublic void contextInitialized(ServletContextEvent sce) {ServletContext application = sce.getServletContext();System.out.println("application"+application.hashCode()+" initialized");}// 监听销毁@Overridepublic void contextDestroyed(ServletContextEvent sce) {ServletContext application = sce.getServletContext();System.out.println("application"+application.hashCode()+" destroyed");}// 监听数据增加@Overridepublic 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);}// 监听数据移除@Overridepublic 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);}// 监听数据修改@Overridepublic 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);}}
3.1.2 定义触发监听器的代码
// ServletA用于向application域中放入数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected 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 {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ServletContext appliation = getServletContext();// 修改application域中的数据appliation.setAttribute("k1","value1");// 删除application域中的数据appliation.removeAttribute("k2");}
}
3.2 session域监听器
HttpSessionListener
监听HttpSession对象的创建与销毁
方法名 | 作用 |
---|---|
sessionCreated(HttpSessionEvent hse) | HttpSession对象创建时调用 |
sessionDestroyed(HttpSessionEvent hse) | HttpSession对象销毁时调用 |
HttpSessionEvent对象
代表从HttpSession对象身上捕获到的事件,- 通过这个事件对象我们可以获取到触发事件的HttpSession对象。
HttpSessionAttributeListener
监听HttpSession中属性的添加、移除和修改
方法名 | 作用 |
---|---|
attributeAdded(HttpSessionBindingEvent se) | 向HttpSession中添加属性时调用 |
attributeRemoved(HttpSessionBindingEvent se) | 从HttpSession中移除属性时调用 |
attributeReplaced(HttpSessionBindingEvent se) | 当HttpSession中的属性被修改时调用 |
HttpSessionBindingEvent对象
代表属性变化事件,它包含的方法如下:
方法名 | 作用 |
---|---|
getName() | 获取修改或添加的属性名 |
getValue() | 获取被修改或添加的属性值 |
getSession() | 获取触发事件的HttpSession对象 |
测试代码 :
3.2.1 定义监听器
@WebListener
public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener {// 监听session创建@Overridepublic void sessionCreated(HttpSessionEvent se) {HttpSession session = se.getSession();System.out.println("session"+session.hashCode()+" created");}// 监听session销毁@Overridepublic void sessionDestroyed(HttpSessionEvent se) {HttpSession session = se.getSession();System.out.println("session"+session.hashCode()+" destroyed");}// 监听数据增加@Overridepublic void attributeAdded(HttpSessionBindingEvent se) {String name = se.getName();Object value = se.getValue();HttpSession session = se.getSession();System.out.println("session"+session.hashCode()+" add:"+name+"="+value);}// 监听数据移除@Overridepublic void attributeRemoved(HttpSessionBindingEvent se) {String name = se.getName();Object value = se.getValue();HttpSession session = se.getSession();System.out.println("session"+session.hashCode()+" remove:"+name+"="+value);}// 监听数据修改@Overridepublic void attributeReplaced(HttpSessionBindingEvent se) {String name = se.getName();Object value = se.getValue();HttpSession session = se.getSession();Object newValue = session.getAttribute(name);System.out.println("session"+session.hashCode()+" change:"+name+"="+value+" to "+newValue);}}
3.2.2 定义触发监听器的代码
// servletA用于创建session并向session中放数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 创建session,并向session中放入数据HttpSession session = req.getSession();session.setAttribute("k1","v1");session.setAttribute("k2","v2");}
}// servletB用于修改删除session中的数据并手动让session不可用
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();// 修改session域中的数据session.setAttribute("k1","value1");// 删除session域中的数据session.removeAttribute("k2");// 手动让session不可用session.invalidate();}
}
3.3 request域监听器
ServletRequestListener
监听ServletRequest对象的创建与销毁
方法名 | 作用 |
---|---|
requestInitialized(ServletRequestEvent sre) | ServletRequest对象创建时调用 |
requestDestroyed(ServletRequestEvent sre) | ServletRequest对象销毁时调用 |
- ServletRequestEvent对象代表从HttpServletRequest对象身上捕获到的事件,
- 通过这个事件对象我们可以获取到触发事件的HttpServletRequest对象。
- 另外还有一个方法可以获取到当前Web应用的ServletContext对象。
ServletRequestAttributeListener
监听ServletRequest中属性的添加、移除和修改
方法名 | 作用 |
---|---|
attributeAdded(ServletRequestAttributeEvent srae) | 向ServletRequest中添加属性时调用 |
attributeRemoved(ServletRequestAttributeEvent srae) | 从ServletRequest中移除属性时调用 |
attributeReplaced(ServletRequestAttributeEvent srae) | 当ServletRequest中的属性被修改时调用 |
- ServletRequestAttributeEvent对象代表属性变化事件,它包含的方法如下:
方法名 | 作用 |
---|---|
getName() | 获取修改或添加的属性名 |
getValue() | 获取被修改或添加的属性值 |
getServletRequest () | 获取触发事件的ServletRequest对象 |
测试代码:
3.3.1 定义监听器
@WebListener
public class RequestListener implements ServletRequestListener , ServletRequestAttributeListener {// 监听初始化@Overridepublic void requestInitialized(ServletRequestEvent sre) {ServletRequest request = sre.getServletRequest();System.out.println("request"+request.hashCode()+" initialized");}// 监听销毁@Overridepublic void requestDestroyed(ServletRequestEvent sre) {ServletRequest request = sre.getServletRequest();System.out.println("request"+request.hashCode()+" destoryed");}// 监听数据增加@Overridepublic void attributeAdded(ServletRequestAttributeEvent srae) {String name = srae.getName();Object value = srae.getValue();ServletRequest request = srae.getServletRequest();System.out.println("request"+request.hashCode()+" add:"+name+"="+value);}// 监听数据移除@Overridepublic void attributeRemoved(ServletRequestAttributeEvent srae) {String name = srae.getName();Object value = srae.getValue();ServletRequest request = srae.getServletRequest();System.out.println("request"+request.hashCode()+" remove:"+name+"="+value);}// 监听数据修改@Overridepublic void attributeReplaced(ServletRequestAttributeEvent srae) {String name = srae.getName();Object value = srae.getValue();ServletRequest request = srae.getServletRequest();Object newValue = request.getAttribute(name);System.out.println("request"+request.hashCode()+" change:"+name+"="+value+" to "+newValue);}
}
3.3.2 定义触发监听器的代码
// servletA向请求域中放数据
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 向request中增加数据req.setAttribute("k1","v1");req.setAttribute("k2","v2");// 请求转发req.getRequestDispatcher("servletB").forward(req,resp);}
}// servletB修改删除域中的数据
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 修改request域中的数据req.setAttribute("k1","value1");// 删除session域中的数据req.removeAttribute("k2");}
}
3.4 session域的两个特殊监听器
3.4.1 session绑定监听器
HttpSessionBindingListener
监听当前监听器对象在Session域中的增加与移除
方法名 | 作用 |
---|---|
valueBound(HttpSessionBindingEvent event) | 该类的实例被放到Session域中时调用 |
valueUnbound(HttpSessionBindingEvent event) | 该类的实例从Session中移除时调用 |
- HttpSessionBindingEvent对象代表属性变化事件,它包含的方法如下:
方法名 | 作用 |
---|---|
getName() | 获取当前事件涉及的属性名 |
getValue() | 获取当前事件涉及的属性值 |
getSession() | 获取触发事件的HttpSession对象 |
测试代码:
3.4.2 定义监听器
public class MySessionBindingListener implements HttpSessionBindingListener {// 监听绑定@Overridepublic 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);}// 监听解除绑定@Overridepublic 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);}
}
3.4.3 定义监听器
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();// 绑定监听器session.setAttribute("bindingListener",new MySessionBindingListener());// 解除绑定监听器session.removeAttribute("bindingListener");}
}
3.5 钝化活化监听器(序列化与反序列化
HttpSessionActivationListener
监听某个对象在Session中的序列化与反序列化
方法名 | 作用 |
---|---|
sessionWillPassivate(HttpSessionEvent se) | 该类实例和Session一起钝化到硬盘时调用 |
sessionDidActivate(HttpSessionEvent se) | 该类实例和Session一起活化到内存时调用 |
HttpSessionEvent对象
代表事件对象,通过getSession()方法
获取事件涉及的HttpSession对象。
什么是钝化活化 :
- session对象在服务端是以对象的形式存储于内存的,session过多,服务器的内存也是吃不消的
- 而且一旦服务器发生重启,所有的session对象都将被清除,也就意味着session中存储的不同客户端的登录状态丢失
- 为了分摊内存压力 并且为了保证session重启不丢失,我们可以设置将session进行钝化处理
- 在关闭服务器前或者到达了设定时间时,对session进行序列化到磁盘,这种情况叫做session的钝化
- 在服务器启动后或者再次获取某个session时,将磁盘上的session进行反序列化到内存,这种情况叫做session的活化
如何配置钝化活化
- 在web目录下,添加
META-INF
下创建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>
- 请求servletA,获得session,并存入数据,然后重启服务器
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();// 添加数据session.setAttribute("k1","v1");}
}
- 请求servletB获取session,获取重启前存入的数据
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();Object v1 = session.getAttribute("k1");System.out.println(v1);}
}
如何监听钝化活化
- 定义监听器
public class ActivationListener implements HttpSessionActivationListener, Serializable {// 监听钝化@Overridepublic void sessionWillPassivate(HttpSessionEvent se) {HttpSession session = se.getSession();System.out.println("session with JSESSIONID "+ session.getId()+" will passivate");}// 监听活化@Overridepublic 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 {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();// 添加数据session.setAttribute("k1","v1");// 添加钝化活化监听器session.setAttribute("activationListener",new ActivationListener());}
}
总结
- 监听器 Listener , 类似JS 的事件,用于监听 三大域对象的创建销毁以及属性的增删改。
- 域对象发生变化 打印相应信息。
- 实现监听器接口,重写方法,正常写servlet,执行相应的方法,会自动触发监听器。