Java 过滤器(Filter):Java Web 中的请求与响应拦截器
过滤器(Filter)是 Java Web 中用于拦截和处理请求 / 响应的组件,基于 Servlet 容器的函数回调机制工作。它可以在请求到达目标资源(如 Servlet、JSP)前预处理请求,或在响应返回客户端前处理响应,常用于身份验证、日志记录、数据转换等场景。本文将详细解析 Filter 的工作原理、使用方式及典型应用。
Filter 核心概念与作用
什么是 Filter?
Filter 是实现 javax.servlet.Filter 接口的 Java 类,由 Servlet 容器管理,主要作用包括:
- 请求拦截:在请求到达目标资源前进行处理(如验证登录状态、过滤非法参数)。
- 响应处理:在响应返回客户端前进行处理(如压缩数据、添加统一响应头)。
- 链式处理:多个 Filter 可组成过滤器链,按顺序对请求 / 响应进行多级处理。
常见 Filter 类型
根据功能,Filter 可分为以下类型:
- 身份验证过滤器:验证用户登录状态,未登录则重定向到登录页。
- 日志过滤器:记录请求 URL、访问时间、客户端 IP 等信息。
- 数据压缩过滤器:对响应数据进行 GZIP 压缩,减少传输量。
- 编码过滤器:统一设置请求 / 响应的字符编码(如 UTF-8)。
- XSS 过滤器:过滤请求中的恶意脚本,防止跨站脚本攻击。
Filter 接口与生命周期
Filter 接口核心方法
1 | public interface Filter { |
生命周期
Filter 的生命周期由 Servlet 容器管理,分为三个阶段:
- 初始化(
init):- 触发时机:Web 应用启动时(或 Filter 首次被调用时,取决于容器配置)。
- 操作:通过
FilterConfig获取初始化参数(如web.xml中配置的参数),初始化资源。
- 拦截处理(
doFilter):- 触发时机:每次请求匹配 Filter 的拦截规则时。
- 操作:对
ServletRequest/ServletResponse进行处理,调用FilterChain.doFilter()将请求传递给下一个 Filter 或目标资源。
- 销毁(
destroy):- 触发时机:Web 应用卸载或容器关闭时。
- 操作:释放资源(如关闭文件流、数据库连接)。
FilterChain 与 FilterConfig
FilterChain:表示过滤器链,调用其doFilter(request, response)方法可将请求传递给下一个 Filter 或目标资源。若不调用此方法,请求会被拦截,无法到达目标资源。FilterConfig:用于获取 Filter 的配置信息,如初始化参数、Servlet 上下文等:1
2
3
4
5
6// 获取初始化参数
String username = filterConfig.getInitParameter("userName");
// 获取所有参数名称
Enumeration<String> paramNames = filterConfig.getInitParameterNames();
// 获取 ServletContext
ServletContext context = filterConfig.getServletContext();
Filter 的配置与使用
Filter 需通过配置指定拦截规则(如拦截的 URL 路径、Servlet 名称),配置方式有两种:XML 配置和注解配置(Servlet 3.0+)。
XML 配置(web.xml)
1 | <!-- 注册 Filter --> |
url-pattern:指定拦截的 URL 路径,支持通配符(如/*拦截所有请求,/admin/*拦截 admin 路径下的请求)。servlet-name:可替代url-pattern,指定拦截特定 Servlet(如<servlet-name>UserServlet</servlet-name>)。dispatcher:指定拦截的请求类型,可选值:REQUEST:直接访问资源(默认);FORWARD:通过RequestDispatcher.forward()转发的请求;INCLUDE:通过RequestDispatcher.include()包含的请求;ERROR:通过声明式异常处理(如web.xml中<error-page>)跳转的请求。
注解配置(Servlet 3.0+)
无需 web.xml,直接在 Filter 类上添加 @WebFilter 注解:
1 |
|
示例:登录验证 Filter
1 | public class LoginFilter implements Filter { |
过滤器链(Filter Chain)
当多个 Filter 匹配同一请求时,容器会按 filter-mapping 在配置中的顺序 组成过滤器链,依次调用各 Filter 的 doFilter 方法。
执行流程:
- 客户端发送请求 → 容器根据 URL 匹配 Filter 链。
- 按顺序调用第一个 Filter 的
doFilter方法。 - 每个 Filter 处理后,调用
chain.doFilter()传递给下一个 Filter。 - 最后一个 Filter 调用
chain.doFilter()后,请求到达目标资源(如 Servlet)。 - 目标资源处理完成后,响应按 Filter 链的逆序返回,每个 Filter 可继续处理响应。
示例:两个 Filter 的执行顺序
1 | <!-- 过滤器链顺序:FirstFilter → SecondFilter --> |
执行流程:
1 | 请求 → FirstFilter.doFilter() → chain.doFilter() → SecondFilter.doFilter() → chain.doFilter() → 目标资源 |
Filter 与 Servlet 的区别
| 特性 | Filter | Servlet |
|---|---|---|
| 核心功能 | 拦截请求 / 响应,预处理 / 后处理 | 处理请求,生成响应 |
| 触发时机 | 请求到达 Servlet 前 / 响应返回前 | 请求匹配 URL 映射时 |
| 生命周期方法 | init()、doFilter()、destroy() |
init()、service()、destroy() |
| 调用方式 | 链式调用(FilterChain) |
直接调用(容器匹配 URL 后) |
| 典型应用 | 身份验证、日志、编码处理 | 业务逻辑处理、数据交互 |
最佳实践
- 明确拦截范围:避免使用
/*拦截所有请求,应根据功能精准配置url-pattern(如/api/*仅拦截 API 请求)。 - 控制过滤器链顺序:按依赖关系排序(如先执行编码 Filter,再执行身份验证 Filter)。
- 及时释放资源:在
destroy()方法中清理资源(如关闭文件流、线程池),避免内存泄漏。 - 避免长时间操作:
doFilter方法应快速执行,耗时操作(如复杂计算)会阻塞请求处理
v1.3.10