1. Servlet过滤器与侦听器:Web开发的隐形守护者
在Java Web开发中,Servlet技术栈就像一座精密的工厂流水线,而过滤器和侦听器则是这条流水线上两个至关重要的质检员和监控员。它们不直接参与产品制造(请求处理),却在每个环节默默守护着系统的安全与稳定。想象一下,如果没有安检门(过滤器)和监控摄像头(侦听器),我们的Web应用将面临多少潜在风险?
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Servlet过滤器:HTTP请求的安检通道
2.1 过滤器的工作原理与实现
过滤器本质上是一个实现了javax.servlet.Filter接口的Java类,它的工作流程就像机场的安检系统:
java复制public class AuthFilter implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
// 初始化操作,类似安检设备的启动自检
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 前置处理:验证身份(检查登机牌)
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (!checkAuth(httpRequest)) {
((HttpServletResponse)response).sendRedirect("/login");
return;
}
// 放行到下一个过滤器或Servlet(通过安检门)
chain.doFilter(request, response);
// 后置处理:记录日志(保存安检记录)
logAccess(httpRequest);
}
@Override
public void destroy() {
// 资源清理,类似安检设备的关机维护
}
}
关键提示:chain.doFilter()的调用就像安检门的闸机,忘记调用会导致请求被"卡住",这是新手最常犯的错误。
2.2 过滤器的典型应用场景
根据网络热词中提到的实际需求,以下是过滤器的实战用例:
-
身份认证过滤器(对应热词:servlet容器)
- 检查Session/Cookie中的登录状态
- 实现API密钥验证(适合RESTful接口)
-
请求日志过滤器(对应热词:fiddler过滤器)
- 记录请求URL、参数、耗时等元数据
- 过滤静态资源请求(如热词提到的"不要js等静态文件")
-
XSS防护过滤器
- 对请求参数进行HTML标签转义
- 预防SQL注入攻击
-
编码统一过滤器
- 强制设置request/response的字符编码(UTF-8)
- 解决中文乱码问题
-
性能监控过滤器
- 计算请求处理时间
- 识别慢请求并报警
2.3 过滤器的配置方式
在web.xml中的配置示例(传统方式):
xml复制<filter>
<filter-name>authFilter</filter-name>
<filter-class>com.example.AuthFilter</filter-class>
<init-param>
<param-name>excludeUrls</param-name>
<param-value>/login,/static</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>authFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Spring Boot中的注解配置(现代方式):
java复制@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<AuthFilter> authFilter() {
FilterRegistrationBean<AuthFilter> reg = new FilterRegistrationBean<>();
reg.setFilter(new AuthFilter());
reg.addUrlPatterns("/*");
reg.setOrder(1); // 过滤器执行顺序
return reg;
}
}
3. Servlet侦听器:应用状态的监控专家
3.1 侦听器的类型与用途
侦听器就像安装在系统各个关键节点的传感器,主要分为以下几类:
-
ServletContext侦听器
- 对应接口:ServletContextListener
- 应用场景:应用启动时加载缓存,关闭时释放资源
java复制public class AppInitListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { // 模拟缓存预热 CacheManager.loadPopularProducts(); } @Override public void contextDestroyed(ServletContextEvent sce) { // 释放数据库连接池 DataSourceManager.close(); } } -
Session侦听器
- 对应接口:HttpSessionListener
- 应用场景:统计在线用户数,实现强制下线功能
java复制public class SessionTracker implements HttpSessionListener { private static final AtomicInteger counter = new AtomicInteger(); @Override public void sessionCreated(HttpSessionEvent se) { counter.incrementAndGet(); se.getSession().setMaxInactiveInterval(30*60); // 30分钟过期 } @Override public void sessionDestroyed(HttpSessionEvent se) { counter.decrementAndGet(); } } -
Request侦听器
- 对应接口:ServletRequestListener
- 应用场景:记录请求生命周期事件
3.2 侦听器的实战技巧
- 并发控制:Session侦听器中的计数器需要使用AtomicInteger等线程安全类
- 性能优化:避免在侦听器中执行耗时操作,必要时使用异步处理
- 异常处理:侦听器的异常可能导致应用启动失败,需要完善try-catch
4. 过滤器与侦听器的进阶应用
4.1 组合使用案例:接口限流系统
结合过滤器和侦听器实现API限流:
- 使用ServletContext侦听器初始化令牌桶
- 通过过滤器进行请求限流判断
- 借助Session侦听器实现用户级限流
java复制// 在过滤器中实现限流
public class RateLimitFilter implements Filter {
private RateLimiter limiter;
@Override
public void init(FilterConfig config) {
// 从ServletContext获取侦听器初始化的限流器
limiter = (RateLimiter)config.getServletContext()
.getAttribute("rateLimiter");
}
@Override
public void doFilter(...) {
if (!limiter.tryAcquire()) {
response.setStatus(429);
return;
}
chain.doFilter(request, response);
}
}
4.2 性能监控系统搭建
- 使用ServletRequestListener记录请求开始/结束时间
- 通过Filter统计处理耗时
- 定时将数据导出到监控系统(如热词提到的zabbix)
5. 常见问题排查指南
5.1 过滤器不生效的排查步骤
-
检查web.xml配置或注解是否正确
<url-pattern>是否匹配目标路径- 注解扫描包路径是否正确
-
确认过滤器顺序
- 通过
@Order或<filter-mapping>顺序控制 - 注意:web.xml中filter-mapping的顺序决定执行顺序
- 通过
-
检查是否调用了chain.doFilter()
- 忘记调用会导致请求链中断
5.2 侦听器事件丢失问题
-
Session超时事件未触发
- 检查
<session-config>中的超时时间设置 - 确认服务器是否正常关闭(非强制kill)
- 检查
-
ServletContext初始化参数读取失败
- 检查
<context-param>名称是否匹配 - 确认侦听器加载顺序(ContextLoaderListener需优先)
- 检查
6. 现代框架中的演进
虽然原生的Servlet API仍然有效,但在Spring等现代框架中,这些功能有了新的实现方式:
-
过滤器替代方案
- Spring MVC的Interceptor
- Spring Security的FilterChain
-
侦听器替代方案
- Spring的事件机制(ApplicationEvent)
- @PostConstruct/@PreDestroy注解
不过理解原生Servlet机制仍然是Java Web开发的基石,就像了解汽车发动机原理对于赛车手的重要性一样。当我们需要处理底层HTTP细节或优化性能时,这些基础知识就会显示出它们的价值。
