Java:chain.doFilter
chain.doFilter(request, response) 是 Java Servlet 过滤器(Filter)机制中的核心方法,用于将请求传递给过滤器链中的下一个过滤器,或者如果当前过滤器是链中的最后一个,则将请求传递给目标资源(如 Servlet、JSP 或静态资源)。
以下是关于 chain.doFilter 的详细解析:
1. 基本作用与工作原理
传递控制权:在 Filter 接口的 doFilter 方法中,调用 chain.doFilter(request, response) 表示当前过滤器已完成其预处理逻辑,允许请求继续向下传播。
过滤器链执行:Servlet 容器维护一个 FilterChain 对象。当调用 chain.doFilter 时,容器会查找并执行链中的下一个过滤器。如果没有更多过滤器,请求将被发送到最终的 Servlet 或资源。
双向处理:过滤器不仅可以处理进入的请求(Request),还可以处理返回的响应(Response)。代码位于 chain.doFilter 之前的部分在请求到达目标资源前执行;代码位于 chain.doFilter 之后的部分在目标资源处理完毕、响应返回给客户端之前执行。
2. 典型代码结构
一个标准的过滤器实现通常包含以下结构:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 1. 预处理逻辑(请求阶段)
// 例如:记录日志、检查权限、修改请求参数、设置字符编码等
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println("请求URI: " + httpRequest.getRequestURI());
//2. 放行请求,交给下一个过滤器或目标资源
chain.doFilter(request, response);
// 3. 后处理逻辑(响应阶段)
// 例如:记录响应时间、压缩响应数据、修改响应头等
HttpServletResponse httpResponse = (HttpServletResponse) response;
System.out.println("响应状态码: " + httpResponse.getStatus());
}
3. 关键注意事项
A. 必须调用以完成请求
如果在 doFilter 方法中没有调用 chain.doFilter(request, response),请求将在此处中断,不会到达目标资源,客户端通常会收到空白页面或超时错误。这通常用于拦截非法请求(如未登录用户访问受保护资源),此时过滤器应直接通过 response 对象返回错误信息或重定向。
B. 请求与响应的包装
如果需要修改请求或响应的内容(例如修改请求参数或压缩响应输出),不能直接传递原始的 request 和 response 对象,而应该传递包装后的对象(如 HttpServletRequestWrapper 或 HttpServletResponseWrapper)。
C. 异常处理
chain.doFilter 可能会抛出 IOException 或 ServletException。在实际开发中,通常需要在 try-catch-finally 块中调用它,以确保即使后续处理发生异常,当前过滤器也能执行必要的清理工作或记录错误日志。
4. 在 Spring Security 中的应用
在 Spring Security 中,chain.doFilter 是责任链模式的核心体现。安全过滤器链(Filter Chain)由多个过滤器组成(如认证过滤器、授权过滤器等)。每个过滤器在执行完自己的安全逻辑后,调用 chain.doFilter 将请求传递给下一个安全过滤器,直到所有安全检查通过,请求才到达应用程序的控制器。
5. 常见应用场景
- 身份验证与授权:检查用户是否登录,是否有权限访问特定资源。若未通过,则不调用 chain.doFilter,直接返回 401 或 403 状态码。
- 日志记录:在调用 chain.doFilter 前后记录请求的开始时间和结束时间,计算处理耗时。
- 字符编码设置:在请求到达 Servlet 之前,统一设置请求和响应的字符编码(如 UTF-8),防止乱码。
- 跨域处理(CORS):添加必要的 CORS 响应头,允许跨域请求。
