Skip to content

J2EE_008 Filter 笔记


目录

  1. Filter 简介
  2. Filter 核心API
  3. Filter 创建与配置
  4. Filter 生命周期
  5. Filter 执行流程
  6. Filter 常见应用场景
  7. Filter 执行顺序控制
  8. Filter 高级特性
  9. 常见问题

1. Filter 简介

Filter(过滤器) 是 Java Web 的核心组件之一,用于在 请求到达 Servlet 前响应返回客户端前 对请求/响应进行预处理或后处理。

  • 核心功能:拦截请求和响应,实现通用逻辑(如权限校验、日志记录、编码转换等)。
  • 设计模式:责任链模式(多个 Filter 按顺序处理同一个请求)。
  • 典型应用场景
    • 统一设置请求编码(解决中文乱码)
    • 权限控制(登录校验、角色校验)
    • 日志记录(记录请求耗时、请求参数)
    • 敏感词过滤(替换响应内容)

2. Filter 核心API

接口/类核心方法说明
javax.servlet.Filterinit(FilterConfig)
doFilter(ServletRequest, ServletResponse, FilterChain)
destroy()
Filter 接口定义的生命周期方法
FilterConfiggetInitParameter(String)获取 Filter 初始化参数
FilterChaindoFilter(ServletRequest, ServletResponse)调用链,决定是否放行到下一个 Filter/Servlet

3. Filter 创建与配置

方式1: 注解配置(Servlet 3.0+)

java
@WebFilter(
    urlPatterns = "/*",                  // 拦截路径(支持通配符)
    initParams = { @WebInitParam(name = "charset", value = "UTF-8") }  // 初始化参数
)  
public class EncodingFilter implements Filter {  
    private String charset;  

    @Override  
    public void init(FilterConfig config) {  
        charset = config.getInitParameter("charset");  // 获取初始化参数  
    }  

    @Override  
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)  
            throws IOException, ServletException {  
        req.setCharacterEncoding(charset);  
        resp.setContentType("text/html;charset=" + charset);  
        chain.doFilter(req, resp);  // 放行请求  
    }  

    @Override  
    public void destroy() {}  
}

方式2: web.xml 配置

xml
<!-- 声明 Filter -->  
<filter>  
    <filter-name>AuthFilter</filter-name>  
    <filter-class>com.example.AuthFilter</filter-class>  
    <init-param>  
        <param-name>excludePages</param-name>  
        <param-value>/login,/register</param-value>  
    </init-param>  
</filter>  

<!-- 配置 Filter 拦截路径 -->  
<filter-mapping>  
    <filter-name>AuthFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
    <dispatcher>REQUEST</dispatcher>  <!-- 拦截类型:REQUEST, FORWARD, ERROR 等 -->  
</filter-mapping>

4. Filter 生命周期

  1. 初始化阶段
    • 当 Web 应用启动时,容器调用 init() 方法,仅执行一次
    • 通过 FilterConfig 获取初始化参数。
  2. 拦截处理阶段
    • 每次请求匹配拦截路径时,执行 doFilter() 方法。
  3. 销毁阶段
    • 当 Web 应用关闭时,容器调用 destroy() 方法,释放资源。

5. Filter 执行流程

客户端请求 → Tomcat 容器 → Filter1 → Filter2 → ... → Servlet →  
响应生成 → Filter2 → Filter1 → 客户端
  • 关键点
    • chain.doFilter(req, resp) 表示将请求传递给下一个 Filter 或目标 Servlet。
    • 若某个 Filter 未调用 chain.doFilter(),则请求终止,响应直接返回客户端。

6. Filter 常见应用场景

场景1:全局编码过滤器

java
public void doFilter(...) {  
    req.setCharacterEncoding("UTF-8");  
    resp.setContentType("text/html;charset=UTF-8");  
    chain.doFilter(req, resp);  
}

场景2:登录权限校验

java
public void doFilter(...) {  
    HttpServletRequest request = (HttpServletRequest) req;  
    HttpSession session = request.getSession(false);  

    if (session == null || session.getAttribute("user") == null) {  
        resp.getWriter().write("请先登录!");  
        return;  
    }  
    chain.doFilter(req, resp);  
}

场景3:接口耗时统计

java
public void doFilter(...) {  
    long start = System.currentTimeMillis();  
    chain.doFilter(req, resp);  
    long end = System.currentTimeMillis();  
    System.out.println("请求耗时:" + (end - start) + "ms");  
}

7. Filter 执行顺序控制

  • 规则1web.xml<filter-mapping> 的声明顺序决定 Filter 执行顺序。
  • 规则2:使用注解配置时,顺序不可控,可通过 @Order 注解(部分框架支持)或改为 XML 配置。
  • 强制顺序示例(web.xml):
    xml
    <filter-mapping><filter-name>FilterA</...></filter-mapping>  
    <filter-mapping><filter-name>FilterB</...></filter-mapping>  
    <!-- 执行顺序:FilterA → FilterB -->

8. Filter 高级特性

1. 动态拦截路径

通过 HttpServletRequest 判断请求路径,实现动态拦截:

java
String path = ((HttpServletRequest) req).getRequestURI();  
if (path.startsWith("/admin")) {  
    // 执行管理员权限校验  
}

2. 包装请求/响应对象

通过 ServletRequestWrapperServletResponseWrapper 修改请求参数或响应内容:

java
public void doFilter(...) {  
    // 包装请求对象,修改参数  
    ServletRequest wrappedReq = new HttpServletRequestWrapper((HttpServletRequest) req) {  
        @Override  
        public String getParameter(String name) {  
            String value = super.getParameter(name);  
            return value == null ? "" : value.trim();  // 自动去除参数空格  
        }  
    };  
    chain.doFilter(wrappedReq, resp);  
}

3. 异步处理支持(Servlet 3.0+)

在 Filter 中处理异步请求:

java
public void doFilter(...) {  
    AsyncContext asyncContext = req.startAsync();  
    asyncContext.start(() -> {  
        // 异步处理逻辑  
        asyncContext.complete();  
    });  
}

9. 常见问题

Q1:Filter 不生效可能原因?

  • 拦截路径配置错误(如 urlPatterns 未匹配到请求路径)。
  • 未调用 chain.doFilter() 导致请求终止。
  • Filter 类未正确配置(如 web.xml 中类名拼写错误)。

Q2:如何排除某些路径不过滤?

在 Filter 的 doFilter() 方法中判断请求路径并放行:

java
String path = ((HttpServletRequest) req).getRequestURI();  
if (path.startsWith("/static") || path.equals("/login")) {  
    chain.doFilter(req, resp);  
    return;  
}

Q3:Filter 与 Spring Interceptor 的区别?

FilterInterceptor
Servlet 规范组件Spring 框架组件
依赖 Servlet 容器依赖 Spring 容器
可拦截所有请求(包括静态资源)只能拦截 Controller 层的请求

总结

Filter 是 Java Web 开发中实现 横切关注点 的核心技术,通过统一处理请求和响应,可大幅提升代码复用性和可维护性。合理使用 Filter 能有效解决编码、安全、日志等共性问题。