Filter和Listener是Servlet规范中的两个高级特性,不同于Servlet,它们不用于处理客户端请求。
Filter用于对请求对象 request、response对象进行修改。
Listener用于对context、session、request事件进行监听。
善于使用Servlet规范中的这两个高级特性能够轻松地解决一些特殊问题。

一、Listener 监听器 - Servlet事件监听器概述

在程序开发中,经常需要对某些事件进行监听人,如:监听鼠标单击事件、监听键盘按下事件等,此时就需要使用监听器,监听器在监听的过程中会涉及几个重要的组成部分,具体如下:
① 事件(Event):用户的一个操作,如单击一个按钮、调用一个方法、创建一个对象等。
② 事件源:产生事件的对象。
③ 事件监听器(Listener):负责监听发生在事件源上的事件。
④ 事件处理器:监听器的成员方法,当事件发生的时候会触发对应的处理器(成员方法)。当用户进行一个操作触发事件源上的事件时,就会被事件监听器监听到。当监听器监听到事件发生时,相应的事件处理器就会对发生的事件处理。
事件监听器在进行工作时,可分为几个步骤,具体如下:
① 将监听器绑定到事件源,也就是注册监听器。
② 事件发生时会触发监听器的成员方法,即事件处理器,传递事件对象。
③ 事件处理器通过事件对象获得事件源,并对事件源进行处理。
在开发Web应用程序时, 也经常会使用监听器,这个监听器也被称为Servlet事件监听器。Servlet监听器就是一个实现了特定接口的Java程序,专门用于监听Web应用程序中ServletContext 、HttpSession、和ServletRequest 等域对象的创建、销毁过程,监听这些域对象属性的修改以及感知绑定到HttpSession 域中某个对象的状态。

Servlet规范中共有8种监听器,如下:

类型 描述
ServletContextListener 用于监听ServletContext对象的创建与销毁过程
HttpSessionListener 用于监听HttpSession对象的创建和销毁过程
ServletRequestListener 用于监听ServletRequest对象的创建和销毁过程
ServletContextAttributeListener 用于监听ServletContext对象中的属性变更
HttpSessionAttributeListener 用于监听HttpSession对象中的属性变更
ServletRequestAttributeListener 用于监听ServletRequest对象中的属性变更
HttpSessionBindingListener 用于监听JavaBean对象绑定到HttpSession对象和从HttpSession对象解绑的事件
HttpSessionActivationListener 用于监听HttpSession中对象活化和钝化的过程

IMG20211118202404.jpg

二、监听Servlet域对象的生命周期

要想对Servlet域对象的生命周期进行监听,首先需要实现域对象的 ServletContextListener、HttpSessionListener、ServletRequestListener接口,这些接口中的方法和执行过程非常类似。
可以为每个监听器编写一个单独的类,也可以用一个类来实现这3个接口,从而让这个类具有3个事件监听器
的功能。

实例:创建监听器

  1. public class MyListener implements ServletContextListener, HttpSessionListener, ServletRequestListener {
  2. @Override
  3. public void contextInitialized(ServletContextEvent sce) {
  4. System.out.println("MyListener....ServletContext 对象被创建..... ");
  5. }
  6. @Override
  7. public void contextDestroyed(ServletContextEvent sce) {
  8. System.out.println("MyListener....ServletContext 对象被销毁..... ");
  9. }
  10. @Override
  11. public void sessionCreated(HttpSessionEvent se) {
  12. System.out.println("MyListener....HttpSession 对象被创建..... ");
  13. }
  14. @Override
  15. public void sessionDestroyed(HttpSessionEvent se) {
  16. System.out.println("MyListener....HttpSession 对象被销毁..... ");
  17. }
  18. @Override
  19. public void requestInitialized(ServletRequestEvent sre) {
  20. System.out.println("MyListener....ServletRequest 对象被创建..... ");
  21. }
  22. @Override
  23. public void requestDestroyed(ServletRequestEvent sre) {
  24. System.out.println("MyListener....ServletRequest 对象被销毁..... ");
  25. }
  26. }
  1. <!--监听Servlet域对象 生命周期节点 监听器-->
  2. <listener>
  3. <listener-class>cn.qccr.listener.MyListener</listener-class>
  4. </listener>

需要注意的是,对于Servlet2.3规范,Web.xml 文件中的元素必须位于所有的元素之前以及所有元素之后,否则Web容器在启动时将会提示错误信息。
对于servlet2.4以及以后的规范,这些同级别的元素之间的顺序可以任意。
一个完整的Servlet事件监听器包括Listener类和配置信息,而一个Web.xml中可以配置多个监听器。同一种类型的监听器也可以配置多个,触发的时候服务器会顺序执行各个监听器的相应方法。

三、监听Servlet域对象的属性变更

实现ServletContextAttributeListener 、HttpSessionAttributeListener、ServletRequestAttributeListener

  1. public class MyAttributeListener implements ServletContextAttributeListener,
  2. HttpSessionAttributeListener, ServletRequestAttributeListener {
  3. @Override
  4. public void attributeAdded(ServletContextAttributeEvent event) {
  5. String name = event.getName();
  6. Object value = event.getValue();
  7. System.out.println("=== MyAttributeListener ... ServletContext 添加属性:" + name + "=" +event.getServletContext().getAttribute(name) + "value = " + value);
  8. System.out.println();
  9. }
  10. @Override
  11. public void attributeRemoved(ServletContextAttributeEvent event) {
  12. String name = event.getName();
  13. System.out.println("=== MyAttributeListener ... ServletContext 移除属性:" + name);
  14. System.out.println();
  15. }
  16. @Override
  17. public void attributeReplaced(ServletContextAttributeEvent event) {
  18. String name = event.getName();
  19. System.out.println("=== MyAttributeListener ... ServletContext替换属性:" + name + "=" +event.getServletContext().getAttribute(name));
  20. System.out.println();
  21. }
  22. @Override
  23. public void attributeAdded(HttpSessionBindingEvent event) {
  24. String name = event.getName();
  25. System.out.println("=== MyAttributeListener ... HttpSession添加属性:" + name + "=" +event.getSession().getAttribute(name));
  26. System.out.println();
  27. }
  28. @Override
  29. public void attributeRemoved(HttpSessionBindingEvent event) {
  30. String name = event.getName();
  31. System.out.println("=== MyAttributeListener ... HttpSession移除属性:" + name + "=" +event.getSession().getAttribute(name));
  32. System.out.println();
  33. }
  34. @Override
  35. public void attributeReplaced(HttpSessionBindingEvent event) {
  36. String name = event.getName();
  37. System.out.println("=== MyAttributeListener ... HttpSession替换属性:" + name + "=" + event.getSession().getAttribute(name));
  38. System.out.println();
  39. }
  40. @Override
  41. public void attributeAdded(ServletRequestAttributeEvent srae) {
  42. String name = srae.getName();
  43. System.out.println("=== MyAttributeListener ... ServletRequest添加属性:" + name + "=" +srae.getServletContext().getAttribute(name));
  44. System.out.println();
  45. }
  46. @Override
  47. public void attributeRemoved(ServletRequestAttributeEvent srae) {
  48. String name = srae.getName();
  49. System.out.println("=== MyAttributeListener ... ServletRequest添加移除:" + name + "=" +srae.getServletContext().getAttribute(name));
  50. System.out.println();
  51. }
  52. @Override
  53. public void attributeReplaced(ServletRequestAttributeEvent srae) {
  54. String name = srae.getName();
  55. System.out.println("=== MyAttributeListener ... ServletRequest替换属性:" + name + "=" +srae.getServletContext().getAttribute(name));
  56. System.out.println();
  57. }
  58. }
  1. <!--监听Servlet域对象属性变更监听器-->
  2. <listener>
  3. <listener-class>cn.qccr.listener.MyAttributeListener</listener-class>
  4. </listener>