Filter+Listener核心技术
一.filter过滤器
- javaweb三大组件:filter、listener、servlet.
- 过滤器是向web应用程序的请求和响应处理添加功能的web服务组件,可以在访问资源之前对请求和响应进行修改、判断、拦截

- 实现方式
- 实现filter(javax.servlet)接口并重写dofilter方法,一定要保留chain.doFilter(request,response);, 相当于放行功能
- 在web.xml文件中配置过滤器
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(filterName = "LoginFilter") public class LoginFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //1.ServletRequest是HttpServletRequest的父类,需要强转 HttpServletRequest httpServletRequest=(HttpServletRequest)req; //2.获取session和路径 var user = httpServletRequest.getSession().getAttribute("user"); var servletPath = httpServletRequest.getServletPath(); if(null==user && !servletPath.contains("login")){ req.getRequestDispatcher("login.jsp").forward(req,resp); }else chain.doFilter(req, resp); } public void init(FilterConfig config) throws ServletException { } }
<filter> <filter-name>LoginFilter</filter-name> <filter-class>LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/main.jsp</url-pattern> </filter-mapping>
1.filter接口
- javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选操作
- 生命周期: 构造方法--初始化init--有阻拦调阻拦dofilter--结束就销毁
| 方法声明 | 功能介绍 |
| void init(FilterConfig filterConfig) | 实现过滤器的初始化操作 |
| void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) | 执行过滤操作的功能 |
| void destroy() | 实现过滤器的销毁操作 |
- 执行结果:构造过滤器---过滤器正在初始化---阻拦一切html文件,不放行---过滤器销毁了
<filter> <filter-name>LifeFilter</filter-name> <filter-class>LifeFilter</filter-class> </filter> <filter-mapping> <filter-name>LifeFilter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping>
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "LifeFilter") public class LifeFilter implements Filter { public LifeFilter() { System.out.println("构造过滤器"); } public void destroy() { System.out.println("过滤器销毁了"); } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("阻拦一切html文件,不放行"); } public void init(FilterConfig config) throws ServletException { System.out.println("过滤器正在初始化"); } }
2.filterConfig接口
- javax.servlet.FilterConfig接口主要用于描述过滤器的配置信息
- 在配置文件中初始化过滤器配置信息init-param
| 方法声明 | 功能介绍 |
| String getFilterName() | 获取过滤器的名字 |
| String getInitParameter(String name) | 获取指定的初始化参数信息 |
| Enumeration getInitParameterNames() | 获取所有的初始化操作名称 |
| ServletContext getServletContext() | 获取ServletContext对象 |
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; import java.util.Enumeration; @WebFilter(filterName = "FilterConfig") public class FilterConfig implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { chain.doFilter(req, resp); } public void init(javax.servlet.FilterConfig config) throws ServletException { System.out.println(config.getFilterName());//获取过滤器名字FilterConfig System.out.println(config.getInitParameter("name"));//获取参数值,指定的初始化参数信息admin var names = config.getInitParameterNames();//获取所有初始化的参数名 while (names.hasMoreElements()){ System.out.println(names.nextElement());//pass sex name age } System.out.println(config.getServletContext());//获取ServletContext对象信息 org.apache.catalina.core.ApplicationContextFacade@d5319d5 } }
<filter> <filter-name>FilterConfig</filter-name> <filter-class>FilterConfig</filter-class> <init-param> <param-name>name</param-name> <param-value>admin</param-value> </init-param> <init-param> <param-name>pass</param-name> <param-value>123466</param-value> </init-param> <init-param> <param-name>sex</param-name> <param-value>female</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>16</param-value> </init-param> </filter> <filter-mapping> <filter-name>FilterConfig</filter-name> <url-pattern>*.avi</url-pattern> </filter-mapping>
3. 多个过滤器的使用
- 如果有多个过滤器都满足过滤的条件,则容器依据配置文件映射的先后顺序来调用各个过滤器
- 执行顺序:浏览器访问资源先访问过滤器1,2,3; 资源返回时先返回过滤器3,2,1
- 优点:
- 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行;
- 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护

- 执行结果:第一个过滤器---第二个过滤器---第三个过滤器---返回第三个过滤器----返回第二个过滤器--返回第一个过滤器
- 执行顺序跟配置文件映射的顺序相对应
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <filter> <filter-name>FilterA</filter-name> <filter-class>FilterA</filter-class> </filter> <filter-mapping> <filter-name>FilterA</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter> <filter-name>FilterB</filter-name> <filter-class>FilterB</filter-class> </filter> <filter-mapping> <filter-name>FilterB</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter> <filter-name>FilterC</filter-name> <filter-class>FilterC</filter-class> </filter> <filter-mapping> <filter-name>FilterC</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> </web-app>
import jdk.swing.interop.SwingInterOpUtils; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "FilterA") public class FilterA implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("第一个过滤器"); chain.doFilter(req, resp); System.out.println("返回第一个过滤器"); } public void init(FilterConfig config) throws ServletException { } } //--------------------------- import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "FilterB") public class FilterB implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("第二个过滤器"); chain.doFilter(req, resp); System.out.println("返回第二个过滤器"); } public void init(FilterConfig config) throws ServletException { } } //-------------- import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "FilterC") public class FilterC implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { System.out.println("第三个过滤器"); chain.doFilter(req, resp); System.out.println("返回第三个过滤器"); } public void init(FilterConfig config) throws ServletException { } }
二、listener监听器
- Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
- 容器产生的事件主要包括:与生命周期相关的事件、与属性状态相关的事件、与存值状态相关的事件
- 实现方式:采用接口回调的方式,实现各监听器接口。
| 监听器类型 | 功能介绍 |
| javax.servlet.ServletRequestListener | 监听request作用域的创建和销毁 |
| javax.servlet.ServletRequestAttributeListener | 监听request作用域的属性状态变化 |
| javax.servlet.http.HttpSessionListener | 监听session作用域的创建和销毁 |
| javax.servlet.http.HttpSessionAttributeListener | 监听session作用域的属性状态变化 |
| javax.servlet.ServletContextListener | 监听application作用域的创建和销毁 |
| javax.servlet.ServletContextAttributeListener | 监听application作用域的属性状态变化 |
| javax.servlet.http.HttpSessionBindingListener | 监听对象与session的绑定和解除 |
| javax.servlet.http.HttpSessionActivationListener | 监听session数值的钝化和活化 |
1.ServletRequestListener监听器
- 在ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
- 常用方法:
| 方法声明 | 功能介绍 |
| void requestInitialized(ServletRequestEvent sre) | 实现ServletRequest对象的初始化 |
| void requestDestroyed(ServletRequestEvent sre) | 实现ServletRequest对象的销毁 |
import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; public class MyServletRequestListener implements ServletRequestListener { //ServletRequest创建和关闭时 //利用idea时会自动打开浏览器,就会创建两次 //ServletRequest创建了 //ServletRequest关闭了 //ServletRequest创建了 //ServletRequest关闭了 @Override public void requestDestroyed(ServletRequestEvent servletRequestEvent) { System.out.println("ServletRequest关闭了"); } //改为手动打开浏览器访问时,访问时创建,关闭时关闭 //ServletRequest创建了 //ServletRequest关闭了 @Override public void requestInitialized(ServletRequestEvent servletRequestEvent) { System.out.println("ServletRequest创建了"); } }
<listener> <listener-class>MyServletRequestListener</listener-class> </listener>
2. ServletRequestAttributeListener监听器
- 向ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
- 常用方法:
| 方法声明 | 功能介绍 |
| void attributeAdded(ServletRequestAttributeEvent srae) | 增加属性时触发 |
| void attributeReplaced(ServletRequestAttributeEvent srae) | 修改属性时触发 |
| void attributeRemoved(ServletRequestAttributeEvent srae) | 删除属性时触发 |
-
执行结果:修改属性org.apache.catalina.ASYNC_SUPPORTED:true---增加属性name:zhangfei---修改属性name:zhangfei---删除属性name
- 注意:这里修改属性并没有把修改后的属性值打印输出
import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; public class MyServletRequestAttributeListener implements ServletRequestAttributeListener { //当请求附带属性时监听 @Override public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) { System.out.println("增加属性"+servletRequestAttributeEvent.getName()+":"+servletRequestAttributeEvent.getValue());//增加属性 } @Override public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) { System.out.println("删除属性"+servletRequestAttributeEvent.getName());//删除属性 } @Override public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) { System.out.println("修改属性"+servletRequestAttributeEvent.getName()+":"+servletRequestAttributeEvent.getValue());//修改属性 } }
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/2/9 Time: 12:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>MyServletRequestAttributeListener监听request属性</title> </head> <body> <% request.setAttribute("name","zhangfei"); //增加属性 request.setAttribute("name","guanyu"); //修改属性 request.removeAttribute("name");//删除属性 %> </body> </html>
<listener> <listener-class>MyServletRequestAttributeListener</listener-class> </listener>
3. HttpSessionListener监听器
- 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器。
- 常用方法如下:
| 方法声明 | 功能介绍 |
| void sessionCreated(HttpSessionEvent se) |
当一个HttpSession对象被创建时会调用这个方法 |
| void sessionDestroyed(HttpSessionEvent se) |
当一个HttpSession超时或者调用HttpSession invalidate()方法让它销毁时,将会调用这个方法 |
<listener> <listener-class>MyHttpSessionListener</listener-class> </listener> <!--观察不到会话销毁的原因是因为会话的生命周期默认为30分钟,自定义会话存活时间为3s,就会自动销毁会话--> <session-config> <session-timeout>1</session-timeout> </session-config>
import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class MyHttpSessionListener implements HttpSessionListener{ @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { System.out.println("会话创建"); } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("会话销毁"); } }
4. HttpSessionAttributeListener监听器
- HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器。
- 常用方法如下
| 方法声明 | 功能介绍 |
| void attributeAdded(HttpSessionBindingEvent se) | 当往会话中加入一个属性的时候会调用这个 方法 |
| void attributeRemoved(HttpSessionBindingEvent se) |
当从会话中删除一个属性的时候会调用这个 方法 |
| void attributeReplaced(HttpSessionBindingEvent se) |
当改变会话中的属性的时候会调用这个方法 |
- 执行结果:增加属性name:zhangfei---修改属性name:zhangfei---删除属性name
import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener { @Override public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("增加属性"+httpSessionBindingEvent.getName()+":"+httpSessionBindingEvent.getValue());//增加属性 } @Override public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("删除属性"+httpSessionBindingEvent.getName());//删除属性 } @Override public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("修改属性"+httpSessionBindingEvent.getName()+":"+httpSessionBindingEvent.getValue());//修改属性 } }
<listener> <listener-class>MyHttpSessionAttributeListener</listener-class> </listener>
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/2/9 Time: 12:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>MyServletRequestAttributeListener监听request属性</title> </head> <body> <% session.setAttribute("name","zhangfei"); //增加属性 session.setAttribute("name","guanyu"); //修改属性 session.removeAttribute("name");//删除属性 %> </body> </html>
5. ServletContextListener监听器
- 在ServletContext创建和关闭时都会通知ServletContextListener监听器。
- 常用方法如下
| 方法声明 | 功能介绍 |
| void contextInitialized(ServletContextEvent sce) |
当ServletContext创建的时候,将会调用这个方法 |
| void contextDestroyed(ServletContextEvent sce) |
当ServletContext销毁的时候(例如关闭应用服务器 或者重新加载应用),将会调用这个方法 |
- 启动servlet就会创建servlet并监听,终止会销毁
<listener> <listener-class>MyServletContextListener</listener-class> </listener>
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("ServletContext创建"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("ServletContext销毁"); } }
6.ServletContextAttributeListener监听器
- 向ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
- 常用方法如下
| 方法声明 | 功能介绍 |
| void attributeAdded(ServletContextAttributeEvent scae) |
往ServletContext中加入一个属性的时候触发 |
| void attributeRemoved(ServletContextAttributeEvent scae) |
从ServletContext中删除一个属性的时候触发 |
| void attributeReplaced(ServletContextAttributeEvent scae) |
改变ServletContext中属性的时候触发 |
-
执行结果:增加属性name:zhangfei---修改属性name:zhangfei---删除属性name
<listener> <listener-class>MyServletContextAttributeListener</listener-class> </listener>
import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; public class MyServletContextAttributeListener implements ServletContextAttributeListener { @Override public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("增加属性"+servletContextAttributeEvent.getName()+":"+servletContextAttributeEvent.getValue());//增加属性 } @Override public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("删除属性"+servletContextAttributeEvent.getName());//删除属性 } @Override public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("修改属性"+servletContextAttributeEvent.getName()+":"+servletContextAttributeEvent.getValue());//修改属性 } }
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/2/9 Time: 12:11 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>MyServletRequestAttributeListener监听request属性</title> </head> <body> <% application.setAttribute("name","zhangfei"); //增加属性 application.setAttribute("name","guanyu"); //修改属性 application.removeAttribute("name");//删除属性 %> </body> </html>
7. HttpSessionBindingListener监听器
- HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器。
- 常用方法如下
| 方法声明 | 功能介绍 |
| void valueBound(HttpSessionBindingEvent event) | 有对象绑定时调用该方法 |
| void valueUnbound(HttpSessionBindingEvent event) | 有对象解除绑定时调用该方法 |
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/2/9 Time: 12:02 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="com.Person" %> <html> <head> <title>$Title$</title> </head> <body> <% Person person = new Person(); person.setName("zhangfei"); session.setAttribute("person",person); session.removeAttribute("person"); %> </body> </html>
package com; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; public class Person implements HttpSessionBindingListener { private String name; @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Person() { } public Person(String name) { this.name = name; } @Override public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("开始绑定"); } @Override public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("解除绑定"); } }
8. HttpSessionActivationListener监听器
- 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
- 常用方法如下:
| 方法声明 | 功能介绍 |
| void sessionWillPassivate(HttpSessionEvent se) | 有钝化操作时调用该方法 |
| void sessionDidActivate(HttpSessionEvent se) | 有活化操作时调用该方法 |
- 配置context.xml文件的方式如下
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true"> <!-- 配置文件存放的路径信息,可以自由指定 --> <Store className="org.apache.catalina.session.FileStore" directory="C:\session"/> </Manager>
三、案例应用
- 实现功能: 在线人数统计监听
- 监听器
import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class MyListener implements HttpSessionListener, ServletContextListener { ServletContext servletContext=null; @Override public void contextInitialized(ServletContextEvent servletContextEvent) { servletContext = servletContextEvent.getServletContext(); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { servletContext=null; } @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { //将当前的在线人数加上1,并且保存到ServletContext(application)中 System.out.println("有新用户上线"); Object count = servletContext.getAttribute("count"); if (null==count){ servletContext.setAttribute("count",1); }else { Integer num=(Integer) count; num++; servletContext.setAttribute("count",num); } System.out.println("当前在线用户人数为"+servletContext.getAttribute("count")); } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("用户下线"); } }
- 配置文件
<listener> <listener-class>MyListener</listener-class> </listener>
- jsp文件
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2021/2/10 Time: 11:05 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>监听在线用户人数</title> </head> <body> <h1> 当前在线用户人数:${applicationScope.count} </h1> </body> </html>
浙公网安备 33010602011771号