Filter 过滤器详解与使用指南
Filter 过滤器详解与使用指南
一、Filter 概述
1.1 什么是 Filter?
Filter(过滤器)是 Java Servlet 规范中定义的一种特殊组件,用于在请求到达 Servlet 之前或响应发送到客户端之前拦截和处理 HTTP 请求和响应。Filter 可以看作是一个"预处理-后处理"机制。
1.2 Filter 的作用
- 预处理请求:在请求到达目标资源之前进行处理
- 后处理响应:在响应发送到客户端之前进行处理
- 链式处理:多个过滤器可以形成过滤链,依次处理请求和响应
1.3 Filter 的应用场景
- 身份认证和授权检查
- 请求日志记录和审计
- 数据压缩和加密
- 字符编码转换
- 输入验证和XSS防护
- 响应内容过滤和转换
二、Filter 的生命周期
Filter 的生命周期由 Web 容器管理,包含三个阶段:
- 初始化:Web 容器启动时,调用
init()
方法 - 过滤:每次请求时,调用
doFilter()
方法 - 销毁:Web 容器关闭时,调用
destroy()
方法
三、Filter 接口方法
public interface Filter {// 初始化方法,在Filter创建时调用一次void init(FilterConfig filterConfig) throws ServletException;// 过滤处理方法,每次请求都会调用void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;// 销毁方法,在Filter销毁时调用一次void destroy();
}
四、创建和配置 Filter
4.1 创建 Filter 类
// 方式1:实现Filter接口
public class MyFilter implements Filter {private FilterConfig filterConfig;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;System.out.println("MyFilter初始化完成");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 预处理逻辑System.out.println("请求预处理");// 调用过滤链中的下一个过滤器或目标资源chain.doFilter(request, response);// 后处理逻辑System.out.println("响应后处理");}@Overridepublic void destroy() {System.out.println("MyFilter被销毁");this.filterConfig = null;}
}
4.2 配置 Filter
方式1:使用 web.xml 配置(传统方式)
<web-app><!-- 定义Filter --><filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class><!-- 初始化参数 --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><!-- 配置Filter映射 --><filter-mapping><filter-name>MyFilter</filter-name><!-- 匹配所有请求 --><url-pattern>/*</url-pattern><!-- 也可以指定Servlet名称 --><!-- <servlet-name>MyServlet</servlet-name> --><!-- 配置Dispatcher类型 --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher></filter-mapping>
</web-app>
方式2:使用注解配置(Servlet 3.0+)
@WebFilter(filterName = "MyFilter",urlPatterns = {"/*"},initParams = {@WebInitParam(name = "encoding", value = "UTF-8")},dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
)
public class MyFilter implements Filter {// 实现代码同上
}
五、FilterChain 机制
FilterChain 代表一个过滤链,多个过滤器按照配置的顺序依次执行:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 1. 预处理代码(在chain.doFilter()之前执行)System.out.println("Filter1: 预处理");// 2. 将请求传递给下一个过滤器或目标资源chain.doFilter(request, response);// 3. 后处理代码(在chain.doFilter()之后执行)System.out.println("Filter1: 后处理");
}
六、常见 Filter 应用示例
6.1 字符编码过滤器
@WebFilter(urlPatterns = "/*", initParams = {@WebInitParam(name = "encoding", value = "UTF-8")
})
public class CharacterEncodingFilter implements Filter {private String encoding;@Overridepublic void init(FilterConfig filterConfig) {this.encoding = filterConfig.getInitParameter("encoding");if (this.encoding == null) {this.encoding = "UTF-8";}}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 设置请求和响应编码request.setCharacterEncoding(encoding);response.setCharacterEncoding(encoding);response.setContentType("text/html;charset=" + encoding);chain.doFilter(request, response);}@Overridepublic void destroy() {// 清理资源}
}
6.2 身份认证过滤器
@WebFilter(urlPatterns = {"/admin/*", "/user/*"})
public class AuthenticationFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;HttpSession session = httpRequest.getSession(false);// 检查用户是否登录boolean isLoggedIn = (session != null && session.getAttribute("user") != null);if (!isLoggedIn) {// 未登录,重定向到登录页面httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");return;}chain.doFilter(request, response);}
}
6.3 日志记录过滤器
@WebFilter("/*")
public class LoggingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;// 记录请求信息long startTime = System.currentTimeMillis();String requestURI = httpRequest.getRequestURI();String remoteAddr = httpRequest.getRemoteAddr();System.out.println("请求开始: " + requestURI + " from " + remoteAddr);chain.doFilter(request, response);// 记录响应信息long endTime = System.currentTimeMillis();long duration = endTime - startTime;System.out.println("请求完成: " + requestURI + " 耗时 " + duration + "ms");}
}
6.4 XSS 防护过滤器
@WebFilter("/*")
public class XSSFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 包装请求对象,对参数进行XSS过滤XSSRequestWrapper wrappedRequest = new XSSRequestWrapper((HttpServletRequest) request);chain.doFilter(wrappedRequest, response);}
}// XSS请求包装器
class XSSRequestWrapper extends HttpServletRequestWrapper {public XSSRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {String value = super.getParameter(name);return cleanXSS(value);}@Overridepublic String[] getParameterValues(String name) {String[] values = super.getParameterValues(name);if (values == null) return null;String[] cleanedValues = new String[values.length];for (int i = 0; i < values.length; i++) {cleanedValues[i] = cleanXSS(values[i]);}return cleanedValues;}private String cleanXSS(String value) {if (value == null) return null;// 简单的XSS过滤return value.replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'").replaceAll("/", "/");}
}
七、Filter 执行顺序
7.1 执行顺序规则
- web.xml 配置:按照
<filter-mapping>
的配置顺序执行 - 注解配置:按照过滤器类名的字母顺序执行
- 混合配置:web.xml 配置的过滤器先于注解配置的过滤器执行
7.2 控制执行顺序
如果需要精确控制执行顺序,可以使用 web.xml 进行统一配置:
<filter-mapping><filter-name>Filter1</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><filter-mapping><filter-name>Filter2</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><filter-mapping><filter-name>Filter3</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
八、DispatcherType 详解
DispatcherType 用于控制过滤器在哪种类型的请求分发过程中被调用:
DispatcherType | 描述 |
---|---|
REQUEST | 直接来自客户端的请求(默认) |
FORWARD | 通过 RequestDispatcher.forward() 转发的请求 |
INCLUDE | 通过 RequestDispatcher.include() 包含的请求 |
ERROR | 通过错误页面机制转发的请求 |
ASYNC | 异步Servlet处理相关的请求 |
配置示例:
<filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher><dispatcher>ERROR</dispatcher>
</filter-mapping>
九、最佳实践
- 合理设计过滤链:将通用的、轻量级的过滤器放在前面
- 避免重复处理:通过请求属性标记已处理的请求
- 正确处理异常:在过滤器中捕获和处理异常
- 性能考虑:避免在过滤器中执行耗时操作
- 资源清理:在 destroy() 方法中释放资源
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {try {// 预处理// ...chain.doFilter(request, response);// 后处理// ...} catch (Exception e) {// 异常处理throw new ServletException("Filter处理异常", e);}
}
十、总结
Filter 是 Java Web 开发中非常重要的组件,它提供了强大的请求/响应预处理机制。通过合理使用 Filter,可以实现:
- 代码复用:将通用功能抽象为过滤器
- 职责分离:保持 Servlet 专注于业务逻辑
- 灵活配置:通过配置决定过滤器的应用范围和执行顺序
- 功能增强:在不修改现有代码的情况下增强系统功能
掌握 Filter 的使用是 Java Web 开发的基本技能,合理运用 Filter 可以大大提高应用程序的可维护性和扩展性。