FilterChain 详解
FilterChain(过滤器链)是 JavaWeb 中多个 Filter 协同工作的机制,它决定了请求通过多个 Filter 的顺序以及最终如何到达目标资源。
一、FilterChain 核心概念
- 链式结构:多个 Filter 按配置顺序形成处理链
- 责任链模式:每个 Filter 处理请求后决定是否传递给下一个 Filter
- 双向处理:请求进入时正向处理,响应返回时反向处理
二、FilterChain 工作原理
执行流程图示
客户端请求 → Filter1 → Filter2 → ... → FilterN → Servlet → FilterN → ... → Filter2 → Filter1 → 客户端响应
代码层面流程
// 伪代码展示FilterChain执行逻辑
public void doFilter(ServletRequest request, ServletResponse response) {
if (hasNextFilter()) {
nextFilter.doFilter(request, response); // 传递给下一个Filter
} else {
servlet.service(request, response); // 最终到达Servlet
}
// 响应返回时的处理
}
三、FilterChain 关键特性
1. Filter执行顺序控制
1.1 使用注解进行配置时:无明确顺序(可用 @Order 注解在某些框架中指定)
1.2 使用web.xml进行配置时:以Tomcat为例。首先收集所有匹配的Filter映射,然后按以下规则排序:
①首先按URL pattern类型排序(精确 > 路径 > 扩展名)
②同类型按web.xml中出现的顺序
③注解注册的Filter顺序由容器实现决定
④排除重复Filter(相同Filter只执行一次)
2. 中断机制
- 不调用 chain.doFilter():中断链,请求不会继续传递
public void doFilter(...) { if (!isAuthenticated(request)) { response.sendError(403); // 中断链 return; } chain.doFilter(request, response); // 继续执行 }
3. 请求/响应包装
- 可包装请求/响应对象:
public void doFilter(...) { HttpServletRequest wrappedRequest = new CustomRequestWrapper(request); HttpServletResponse wrappedResponse = new CustomResponseWrapper(response); chain.doFilter(wrappedRequest, wrappedResponse); }
四、FilterChain 实际应用
1. 典型过滤器链配置
<!-- web.xml 示例 -->
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/secure/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
2. 多过滤器协作示例
// 编码过滤器
public class EncodingFilter implements Filter {
public void doFilter(...) {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
// 认证过滤器
public class AuthFilter implements Filter {
public void doFilter(...) {
if (checkAuth(request)) {
chain.doFilter(request, response);
} else {
response.sendRedirect("/login");
}
}
}
// 日志过滤器
public class LogFilter implements Filter {
public void doFilter(...) {
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long duration = System.currentTimeMillis() - start;
logRequest(request, duration);
}
}
五、高级应用技巧
1. 动态控制过滤器链
public void doFilter(...) {
if (shouldSkipFilter(request)) {
chain.doFilter(request, response); // 跳过当前过滤逻辑
} else {
// 正常过滤处理
processRequest(request);
chain.doFilter(request, response);
processResponse(response);
}
}
2. 过滤器间数据传递
// 前一个过滤器设置属性
request.setAttribute("filterData", data);
// 后一个过滤器获取属性
Object data = request.getAttribute("filterData");
3. 异步请求处理
@WebFilter(asyncSupported = true)
public class AsyncFilter implements Filter {
public void doFilter(...) {
AsyncContext asyncCtx = request.startAsync();
asyncCtx.addListener(new AsyncListener() {
// 异步回调处理
});
chain.doFilter(request, response);
}
}
六、常见问题解决方案
1. 执行顺序问题
问题:注解配置的过滤器顺序不可控
解决:
- 使用 web.xml 显式配置顺序
- 使用框架提供的排序机制(如 Spring 的
@Order)
2. 性能优化
建议:
- 在 Filter 中缓存常用数据
- 避免在 Filter 中执行耗时操作
- 合理设计 Filter 链长度
3. 异常处理
最佳实践:
public void doFilter(...) {
try {
chain.doFilter(request, response);
} catch (Exception e) {
// 统一异常处理
handleException(e, response);
}
}
七、FilterChain 与拦截器对比
| 特性 | FilterChain | 拦截器(如Spring Interceptor) |
|---|---|---|
| 所处层次 | Servlet 容器层面 | MVC 框架层面 |
| 执行时机 | 更早(在DispatcherServlet之前) | 稍晚(进入Controller之前) |
| 依赖 | 仅依赖Servlet API | 依赖特定框架 |
| 配置方式 | web.xml 或 @WebFilter | 框架配置机制 |
| 访问控制粒度 | 粗粒度(URL模式) | 细粒度(可精确到Controller方法) |
1014

被折叠的 条评论
为什么被折叠?



