一、过滤器(Filter)概述
过滤器(Filter)是 Java Web 开发中的一项重要技术,它允许开发者在请求到达目标资源(如 Servlet、JSP 等)之前或响应返回客户端之前,对请求和响应进行拦截和处理。通过 Filter 技术,可以实现诸如权限控制、日志记录、字符编码设置、敏感词过滤、请求预处理等多种功能。
二、过滤器的工作原理
当客户端发送请求到服务器时,请求首先会经过一系列的 Filter。每个 Filter 可以对请求进行检查和修改,然后将请求传递给下一个 Filter 或目标资源。当目标资源处理完请求后,响应会按照相反的顺序再次经过这些 Filter,每个 Filter 可以对响应进行后处理,最后将响应返回给客户端。
三、创建过滤器
创建 Filter 的基本步骤如下:
-
实现 Filter 接口:编写一个 Java 类,实现
javax.servlet.Filter
接口,并重写其中的三个方法:init()
、doFilter()
和destroy()
。init()
:在 Filter 实例创建后调用,用于初始化资源。doFilter()
:对请求和响应进行处理,是 Filter 的核心方法。destroy()
:在 Filter 实例销毁前调用,用于释放资源。
-
配置 Filter:有两种常见的配置方式:
- 使用
web.xml
配置:<filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class> </filter> <filter-mapping><filter-name>MyFilter</filter-name><url-pattern>/*</url-pattern> </filter-mapping>
- 使用注解配置:
@WebFilter(urlPatterns = "/*") public class MyFilter implements Filter {// 省略方法实现 }
- 使用
四、过滤器链(Filter Chain)
在实际开发中,一个请求可能会经过多个 Filter,这些 Filter 组成一个过滤器链。过滤器链的执行顺序如下:
web.xml
配置:在web.xml
中,<filter-mapping>
标签的配置顺序决定了过滤器的执行顺序。先配置的过滤器会先执行,后配置的过滤器后执行。- 注解配置:使用注解配置时,不同的 Servlet 容器可能有不同的处理方式。有些容器会按照类名的字典序来决定过滤器的执行顺序,而有些容器可能没有明确的顺序。为了确保过滤器按照预期的顺序执行,建议使用
web.xml
进行配置。
五、过滤器的常见应用场景
- 权限控制:通过 Filter 拦截请求,检查用户是否登录或是否有权限访问某个资源。
@WebFilter("/users/*") public class CheckLoginFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;if (req.getSession().getAttribute("login") != null) {chain.doFilter(request, response);} else {resp.sendRedirect("/login.jsp");}} }
- 字符编码设置:解决请求和响应的中文乱码问题。
public class EncodingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");chain.doFilter(request, response);} }
- 日志记录:记录请求的详细信息,便于后续的分析和调试。
public class LogFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("请求时间:" + new Date());chain.doFilter(request, response);} }
- 敏感词过滤:对用户输入的内容进行过滤,防止出现敏感词汇。
六、过滤器的生命周期
Filter 的生命周期由 Servlet 容器管理,主要包括以下三个阶段:
- 初始化(
init()
):当 Filter 被实例化后,Servlet 容器会调用init()
方法进行初始化。可以在该方法中获取初始化参数或进行资源的加载。 - 过滤(
doFilter()
):每次请求到达时,Servlet 容器会调用doFilter()
方法对请求进行处理。 - 销毁(
destroy()
):当 Web 应用被卸载或 Servlet 容器关闭时,Servlet 容器会调用destroy()
方法,释放 Filter 所占用的资源。
七、过滤器的配置细节
-
url-pattern
配置:用于指定 Filter 所拦截的 URL 模式。常见的配置方式包括:- 指定具体资源路径,如
/index.jsp
。 - 指定目录路径,如
/servlet/*
。 - 指定后缀名,如
*.jsp
。 - 使用通配符拦截所有资源,如
/*
。
- 指定具体资源路径,如
-
dispatcher
配置:用于指定 Filter 所拦截的请求类型。常见的值包括:REQUEST
:拦截直接来自客户端的请求。FORWARD
:拦截通过RequestDispatcher
转发的请求。INCLUDE
:拦截通过RequestDispatcher
包含的请求。ERROR
:拦截错误页面的请求。
-
初始化参数(
init-param
):可以在web.xml
中为 Filter 配置初始化参数,并在init()
方法中通过FilterConfig
获取。
八、过滤器的高级应用
-
动态配置 Filter:在某些情况下,可能需要动态地添加或修改 Filter 的配置。可以通过编程方式操作
ServletContext
或使用动态代理技术来实现。 -
与其他技术结合:Filter 可以与 Spring、Spring Boot 等框架结合使用。例如,在 Spring Boot 中,可以通过实现
OncePerRequestFilter
接口来确保每个请求只被过滤一次。 -
分布式环境下的 Filter 应用:在分布式系统中,Filter 可以用于处理跨域请求、统一认证、分布式会话管理等功能。
九、过滤器的性能优化
- 减少不必要的拦截:合理配置
url-pattern
,避免对不需要过滤的资源进行拦截。 - 缓存处理结果:对于一些重复的请求处理逻辑,可以将结果缓存起来,减少重复计算。
- 异步处理:对于一些耗时的操作,可以考虑使用异步方式处理。