1. Filter过滤器核心机制解析
在Web应用开发中,Filter(过滤器)是Java Servlet规范中的重要组件,它像一道安检门,对所有进入应用的请求进行预处理和后续加工。不同于Servlet直接处理业务逻辑,Filter更专注于横切关注点(Cross-Cutting Concerns)的处理,比如安全控制、日志记录、数据转换等通用功能。
1.1 Filter生命周期三阶段
每个Filter实例的生命周期都严格遵循以下三个阶段:
-
初始化阶段:当Web容器(如Tomcat)启动时,会根据web.xml或注解的配置创建Filter实例,并立即调用其init()方法。这个方法只会执行一次,适合进行一次性初始化操作。
-
服务阶段:这是Filter的核心活跃期。每当有匹配的请求到达时,doFilter()方法就会被调用。值得注意的是,这个方法可能被并发调用,因此实现时必须考虑线程安全性。
-
销毁阶段:当Web容器关闭或应用被卸载时,destroy()方法被调用,用于释放Filter占用的资源。这是进行清理工作的最后机会。
1.2 过滤器链运作原理
多个Filter可以组成一个处理链,这是Filter设计的精妙之处。当请求到达时:
- 容器会根据web.xml中
的配置顺序(或注解的order值)依次调用各个Filter的doFilter()方法 - 每个Filter通过FilterChain参数决定是否将请求传递给下一个Filter
- 最后一个Filter调用chain.doFilter()时,请求才会到达目标Servlet
- 响应时则按照相反的顺序经过各个Filter的后处理逻辑
这种机制类似于洋葱模型,请求从外层逐渐向内层传递,响应则从内层返回到外层。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Filter接口实现详解
2.1 init方法:初始化配置
java复制@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 获取web.xml中配置的初始化参数
String paramValue = filterConfig.getInitParameter("myParam");
// 获取ServletContext
ServletContext context = filterConfig.getServletContext();
// 初始化数据库连接池等资源
this.dataSource = initDataSource(context);
}
重要提示:即使不需要初始化操作,也必须重写init()方法,因为它是Filter接口的抽象方法。可以留空但不可省略。
2.2 doFilter方法:核心处理逻辑
java复制@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 1. 类型转换(通常需要Http特有的方法)
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 2. 预处理逻辑
long startTime = System.currentTimeMillis();
logRequestDetails(httpRequest); // 记录请求日志
// 3. 关键:决定是否放行
if (shouldBlockRequest(httpRequest)) {
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
// 4. 包装请求/响应对象(可选)
CustomRequestWrapper wrappedRequest = new CustomRequestWrapper(httpRequest);
// 5. 必须调用chain.doFilter()!
chain.doFilter(wrappedRequest, httpResponse);
// 6. 后处理逻辑
long duration = System.currentTimeMillis() - startTime;
log.debug("请求处理耗时: {}ms", duration);
// 7. 响应加工
compressResponseIfNeeded(httpResponse);
}
2.3 destroy方法:资源清理
java复制@Override
public void destroy() {
// 关闭数据库连接
if (dataSource != null) {
dataSource.close();
}
// 停止后台线程
if (monitorThread != null) {
monitorThread.interrupt();
}
}
3. Filter配置的两种主流方式
3.1 注解配置(推荐用于简单场景)
java复制@WebFilter(
filterName = "myFilter",
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "encoding", value = "UTF-8"),
@WebInitParam(name = "maxSize", value = "1024")
},
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.ASYNC}
)
public class MyFilter implements Filter {
// 实现方法...
}
注解参数说明:
- urlPatterns:支持Ant风格路径匹配(如
/api/*) - dispatcherTypes:控制拦截的请求类型(FORWARD/INCLUDE/ERROR等)
- asyncSupported:是否支持异步处理
3.2 web.xml配置(传统方式)
xml复制<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.example.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
3.3 Spring Boot中的特殊配置
在Spring Boot应用中,除了上述两种方式,还可以通过FilterRegistrationBean进行更灵活的配置:
java复制@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean<LoggingFilter> loggingFilter() {
FilterRegistrationBean<LoggingFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LoggingFilter());
registration.addUrlPatterns("/api/*");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
registration.setName("loggingFilter");
return registration;
}
}
这种方式特别适合需要:
- 精确控制Filter顺序
- 动态决定是否启用某个Filter
- 在Filter中注入Spring管理的Bean
4. 常见Filter应用场景实现
4.1 字符编码过滤器
java复制public class EncodingFilter implements Filter {
private String encoding;
@Override
public void init(FilterConfig config) {
this.encoding = config.getInitParameter("encoding");
if (this.encoding == null) {
this.encoding = "UTF-8";
}
}
@Override
public void doFilter(ServletRequest request, S
