Servlet过滤器与Spring整合的通俗拆解:从“水火不容”到“默契搭档”
一、引子:当Servlet过滤器遇到Spring容器
想象一个场景:你正在开发一个电商系统,需要在用户下单前通过过滤器验证权限。你发现,过滤器中无法直接使用Spring管理的用户服务(UserService
),只能通过笨重的ApplicationContextUtils
手动获取Bean。更头疼的是,过滤器的初始化和销毁逻辑写死在init()
和destroy()
中,无法利用Spring的@PostConstruct
和@PreDestroy
优雅管理资源。
这就是典型的问题场景:
- 依赖注入失效:过滤器由Servlet容器创建,Spring的
@Autowired
注解形同虚设。 - 生命周期割裂:过滤器的初始化和销毁无法与Spring Bean的优雅启停协同工作。
二、破局之道:两种整合方案对比
方案1:中间人代理模式(DelegatingFilterProxy)
角色定位:相当于一个“翻译官”,站在Servlet容器和Spring过滤器之间传递请求。
核心流程(以权限过滤器为例):
-
Servlet容器初始化阶段:
- Servlet容器发现
web.xml
中配置了一个DelegatingFilterProxy
,名为authFilter
。 - 容器调用
authFilter.init()
,但此时它只是一个“空壳”。
// web.xml配置 <filter> <filter-name>authFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter>
- Servlet容器发现
-
Spring容器启动后:
DelegatingFilterProxy
从Spring容器中找到真正的过滤器Bean(如AuthFilter
)。- 如果设置了
targetFilterLifecycle=true
,Spring会调用AuthFilter.init()
(此时AuthFilter
已具备依赖注入能力)。
-
请求处理阶段:
- 当用户访问受保护的URL时,Servlet容器调用
authFilter.doFilter()
。 DelegatingFilterProxy
将请求转交给Spring管理的AuthFilter
执行权限校验。
// Spring管理的真实过滤器 @Component("authFilter") public class AuthFilter implements Filter { @Autowired // 终于能注入Spring Bean了! private UserService userService; @Override public
- 当用户访问受保护的URL时,Servlet容器调用