Filter、Listener学习笔记
Filter 简介
- Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。
- 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Servlet。Servlet 过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。
- Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:
- 在客户端的请求访问后端资源之前,拦截这些请求。
- 在服务器的响应发送回客户端之前,处理这些响应。
Servlet 过滤器方法
过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:
序号 | 方法 & 描述 |
---|---|
1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) 该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。 |
2 | public void init(FilterConfig filterConfig) web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。 |
3 | public void destroy() Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。 |
快速入门
示例1
过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。当 Web 容器启动 Web 应用程序时,它会为您在部署描述符中声明的每一个过滤器创建一个实例。Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前。
Input
web.xml
复制<filter> <!-- 声明Filter名字 --> <filter-name>demo01</filter-name> <!-- 对应的Filter类全名 --> <filter-class>my.stringbug.FilterDemo01</filter-class> </filter> <filter-mapping> <!-- 对应声明的Filter名字 --> <filter-name>demo01</filter-name> <!-- 过滤器的过滤路径 --> <url-pattern>/*</url-pattern> </filter-mapping>
FilterDemo01.java
复制public class FilterDemo01 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("FilterDemo01 过滤器给执行了 ~~"); // 放行(假如没有放行,那么被该过滤器过滤的页面都不会有请求信息和响应信息) filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
index.jsp
复制<body> <h1>Demo 01 ~~~~~</h1> </body>
Output
控制台
复制FilterDemo01 过滤器给执行了 ~~
浏览器页面
复制Demo 01 ~~~~~
示例2
使用注解的方式进行声明,映射到对应的应用程序的部署描述符中的 Servlet 名称或 URL 模式。
Input
FilterDemo02.java
复制// "/*" 访问所有资源之前,都会执行该过滤器 @WebFilter("/*") public class FilterDemo02 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("FilterDemo02 过滤器给执行了 ~~"); // 放行(假如没有放行,那么被该过滤器过滤的页面都不会有请求信息和响应信息) filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
index.jsp
复制<body> <h1>Demo 02 ~~~~~</h1> </body>
Output
控制台
复制FilterDemo02 过滤器给执行了 ~~
浏览器页面
复制Demo 02 ~~~~~
Filter 执行流程 & Filter 生命周期
Filter 执行流程
-
Filter 接口中有一个doFilter 方法,当咱们编写好 Filter,并配置对哪个 web 资源进行拦截后,web 服务器每次在调用 web 资源的 service 方法之前,都会先调用一下 Filter 的 doFilter 方法,因此,在该方法内编写代码可达到如下的:
- 调用目标资源之前,让一段代码执行;
- 是否调用目标资源,即是否让用户访问 web 资源;
- 调用目标资源之后,让一段代码执行。
-
web 服务器在调用 doFilter 方法时,会传递一个 filterChain 对象进来,filterChain 对象是 filter 接口中最重要的一个对象,它也提供了一个 doFilter 方法,开发人员可以根据需求决定是否调用此方法。如果调用该方法,则 web 服务器就会调用 web 资源的 service 方法,即 web 资源就会被访问;否则的话, web 资源就不会被访问。
Filter 生命周期
- init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
- doFilter:每一次请求被拦截资源时,会执行。执行多次
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
Filter 配置说明
拦截路径配置
- 具体资源路径,如:
/index.jsp
- 拦截某个目录,如:
/directory1/directory2/*
- 后缀名拦截,如:
*.html
- 拦截所有资源,如:
/*
拦截方式配置
-
注解配置
属性 类型 说明 asyncSupported boolean 指定Filter是否支持异步模式 dispatcherTypes DispatcherType[ ] 指定Filter对哪种方式的请求进行过滤。
支持的属性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;
默认过滤所有方式的请求filterName String Filter名称 initParams WebInitParam[ ] 配置参数 displayName String Filter显示名 servletNames String[ ] 指定对哪些Servlet进行过滤 urlPatterns/value String[ ] 两个属性作用相同,指定拦截的路径
-
web.xml配置
-
<filter>
指定一个过滤器。<filter-name>
用于为过滤器指定一个名字,该元素的内容不能为空。<filter-class>
元素用于指定过滤器的完整的限定类名。<init-param>
元素用于为过滤器指定初始化参数,它的子元素<param-name>
指定参数的名字,<param-value>
指定参数的值。- 在过滤器中,可以使用
FilterConfig
接口对象来访问初始化参数。
-
<filter-mapping>
元素用于设置一个 Filter 所负责拦截的资源。- 一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径
<filter-name>
子元素用于设置filter的注册名称。该值必须是在<filter>
元素中声明过的过滤器的名字<url-pattern>
设置 filter 所拦截的请求路径(过滤器关联的URL样式)
-
<servlet-name>
指定过滤器所拦截的Servlet名称。 -
<dispatcher>
指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST
,INCLUDE
,FORWARD
和ERROR
之一,默认REQUEST
。用户可以设置多个<dispatcher>
子元素用来指定 Filter 对资源的多种调用方式进行拦截。<dispatcher>
子元素可以设置的值及其意义REQUEST
:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。INCLUDE
:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。FORWARD
:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。ERROR
:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
-
过滤器链
有多个过滤器,过滤器的执行顺序和拦截顺序说明。
过滤器先后顺序问题
-
注解配置:按照类名的字符串比较规则比较,值小的先执行。
如: AFilter 和 BFilter,AFilter先执行。
-
web.xml配置:
谁定义在上边,谁先执行
过滤器执行顺序
如果有两个过滤器:过滤器1和过滤器2
过滤器1
复制@WebFilter(value = "/index.jsp") public class FilterDemo04 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("小明通过过滤器1,去服务器了"); // Filter1 放行 filterChain.doFilter(servletRequest, servletResponse); System.out.println("小明通过过滤器1,从服务器回来了"); } @Override public void destroy() { } }
过滤器2
复制@WebFilter(value = "/index.jsp") public class FilterDemo05 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("小明通过过滤器2,去服务器了"); // Filter2 放行 filterChain.doFilter(servletRequest, servletResponse); System.out.println("小明通过过滤器2,从服务器回来了"); } @Override public void destroy() { } }
index.jsp
复制<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Filter And Listener Demo</title> </head> <body> <% System.out.println("服务器资源被访问了"); %> </body> </html>
启动服务器,访问index.jsp资源,控制台输出:
复制小明通过过滤器1,去服务器了 小明通过过滤器2,去服务器了 服务器资源被访问了 小明通过过滤器2,从服务器回来了 小明通过过滤器1,从服务器回来了
Listener 学习笔记
简介
监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。监听器可以用来检测网站的在线人数,统计网站的访问量等
监听器涉及三个组件:事件源,事件对象,事件监听器
当事件源发生某个动作的时候,它会调用事件监听器的方法,并在调用事件监听器方法的时候把事件对象传递进去。
ServletContextListener
ServletContextListener:监听ServletContext对象的创建和销毁
复制void contextDestroyed(ServletContextEvent sce) // ServletContext对象被销毁之前会调用该方法 void contextInitialized(ServletContextEvent sce) // ServletContext对象创建后会调用该方法
快速入门
- 实现ServletContextListener接口
- 复写方法
- 配置(web.xml配置或注解配置)
实现ServletContextListener接口,复写方法
复制public class ContextLoaderListener implements ServletContextListener { /** * 监听ServletContext对象创建的。ServletContext对象在服务器启动后自动创建。 */ @Override public void contextInitialized(ServletContextEvent servletContextEvent) { // ServletContext对象创建后会调用该方法 System.out.println("ServletContext 对象被创建了"); } /** * 在服务器关闭后,ServletContext对象被销毁。当服务器正常关闭后,该方法会被执行。 */ @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { // ServletContext对象被销毁之前会调用该方法 System.out.println("ServletContext 对象被销毁了"); } }
web.xml配置
复制<listener> <listener-class>my.listener.ContextLoaderListener</listener-class> </listener>
注解配置:在实现监听接口的方法上面添加注解
复制@WebListener("my/listener/contextLoaderListener")
正常的启动服务器,和关闭服务器:控制台输出
启动服务器
复制ServletContext 对象被创建了
关闭服务器
复制ServletContext 对象被销毁了
参考文献
本文来自博客园,作者:LeeHua,转载请注明原文链接:https://www.cnblogs.com/liyihua/p/14477576.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)