前言
基本的Java知识推荐阅读:
从实战中学习:
常用在一些重复代码,需要进行过滤的
1. 基本知识
FilterChain 是 Java 中 Servlet 过滤器机制的重要组成部分,定义了过滤器链的执行顺序和执行逻辑
FilterChain 主要用于控制多个过滤器的依次执行,直到所有过滤器都完成后再交由最终的目标资源(如 Servlet 或 JSP)处理请求
执行流程:
- 过滤器的定义和顺序:多个过滤器会在 web.xml 文件中配置,或者在代码中使用注解(如 @WebFilter)声明
- 过滤器链的构建:容器会根据配置或注解扫描到的过滤器,按顺序构建一个过滤器链(FilterChain)
- 执行顺序:请求到达后,第一个过滤器执行后调用 FilterChain.doFilter() 方法,传递请求到下一个过滤器,依次进行
- 最终资源处理:当过滤器链上的最后一个过滤器执行完毕后,调用目标资源(如 Servlet),开始响应流程
- 响应的返回:执行完目标资源后,响应会沿着过滤器链的反方向依次返回,使每个过滤器有机会处理响应
基本的工作原理如下:
核心方法是 doFilter(ServletRequest request, ServletResponse response),用于将请求和响应传递到过滤器链的下一个过滤器或目标资源
- doFilter 方法:每个过滤器在其 doFilter 方法中调用 chain.doFilter(request, response),会将请求传递到下一个过滤器或目标资源
- 处理请求和响应:过滤器可以在调用 chain.doFilter() 前后执行逻辑,从而对请求和响应进行处理
例如,日志记录、权限校验、编码设置等
2. Demo
一个简单的 FilterChain 示例,展示了两个过滤器(LoggingFilter 和 AuthenticationFilter)如何在 FilterChain 中按顺序工作
1.定义第一个过滤器:LoggingFilter
package FilterChain知识;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/demo/*")
public class LoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("LoggingFilter 初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("LoggingFilter: 请求开始...");
// 执行下一个过滤器或目标资源
chain.doFilter(request, response);
System.out.println("LoggingFilter: 响应返回...");
}
@Override
public void destroy() {
System.out.println("LoggingFilter 销毁");
}
}
2.定义第二个过滤器:AuthenticationFilter
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/demo/*")
public class AuthenticationFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
System.out.println("AuthenticationFilter 初始化");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
Cookie[] cookies = httpRequest.getCookies();
System.out.println(cookies);
if (cookies != null) {
for (Cookie cookie : cookies) {
System.out.println("Found cookie: " + cookie.getName() + "=" + cookie.getValue());
}
}
// 继续执行过滤器链
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("AuthenticationFilter 销毁");
}
}
3.定义目标资源:DemoServlet
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/demo/process")
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DemoServlet: 处理请求...");
resp.getWriter().write("Hello, FilterChain!");
}
}
4.执行流程和结果
当访问 http://localhost:8080/demo/process
时,过滤器链将按顺序执行,以下是执行过程和输出顺序:
- LoggingFilter 开始处理请求
- AuthenticationFilter 进行身份验证
- DemoServlet 处理实际请求并生成响应
- 过滤器以相反顺序返回响应处理
大致的结果如下:
LoggingFilter 初始化
AuthenticationFilter 初始化
LoggingFilter: 请求开始...
AuthenticationFilter: 检查身份验证...
DemoServlet: 处理请求...
AuthenticationFilter: 响应返回后执行...
LoggingFilter: 响应返回...