“Filter 是护城河,Interceptor 是城门守卫。”
如果说 Filter 是应用外围的第一道防线,守护所有进出流量;
那么 Interceptor 就是城内的精锐卫队,只对进入核心区域(Controller)的请求进行精细审查。
两者协同作战,构建了 Web 应用的安全与监控体系。
一、核心概念回顾技术
定义
类比
Filter
Servlet 规范中的组件,在请求到达 Servlet 前拦截,属于容器层
城堡的护城河与外围关卡
Interceptor
Spring MVC 提供的机制,在 Controller 方法执行前后拦截,属于框架层
城内的城门守卫与内务官
二、Filter 深度解析:Servlet 容器的“第一道防线”2.1 Filter 的本质Filter 是 Java Servlet 规范的一部分,由 Servlet 容器(如 Tomcat)管理,不依赖 Spring 框架,因此可以在任何 Java Web 应用中使用。
✅ Filter 的三大生命周期方法:方法
说明
执行时机
init()
初始化
Web 应用启动时调用一次
doFilter()
核心逻辑
每次请求都会调用
destroy()
销毁
Web 应用关闭时调用一次
🔁 执行流程:代码语言:javascript复制Client → Filter1 → Filter2 → ... → Servlet → Controller → View → Filter2 → Filter1 → Client⚠️ 注意:Filter 是双向拦截,既拦截请求,也拦截响应!
2.2 Spring Boot 中使用 Filter✅ 方式一:@WebFilter + @ServletComponentScan代码语言:java复制@WebFilter(urlPatterns = "/api/*", filterName = "encodingFilter")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 设置请求编码
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
System.out.println("EncodingFilter: 请求进入");
chain.doFilter(request, response); // 放行
System.out.println("EncodingFilter: 响应返回");
}
}代码语言:java复制@SpringBootApplication
@ServletComponentScan // 扫描 @WebFilter 注解
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}✅ 方式二:通过 @Bean 注册(推荐)代码语言:java复制@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean
FilterRegistrationBean
registrationBean.setFilter(new EncodingFilter());
registrationBean.addUrlPatterns("/api/*");
registrationBean.setOrder(1); // 执行顺序
return registrationBean;
}
}✅ 优势:支持 @Order 控制执行顺序,更灵活。
2.3 Filter 的典型应用场景场景
示例
统一编码设置
解决中文乱码问题
安全过滤
XSS 过滤、SQL 注入防护
日志记录
记录所有请求的 IP、路径、耗时
Gzip 压缩
对响应内容进行压缩
跨域处理
添加 CORS 响应头
身份认证
JWT 校验、Token 解析(在 Spring Security 中常用)
三、Interceptor 深度解析:Spring MVC 的“智能守卫”3.1 Interceptor 的三大拦截时机Interceptor 是 Spring MVC 的组件,只能拦截被 DispatcherServlet 处理的请求(即映射到 Controller 的请求)。
✅ 三个核心方法:方法
执行时机
是否可终止流程
典型用途
preHandle()
Controller 方法执行前
✅ 可返回 false 终止
权限校验、登录验证
postHandle()
Controller 执行后,视图渲染前
❌ 已执行,无法终止
修改 Model、添加公共数据
afterCompletion()
请求处理完成(包括异常)
❌ 无法终止
资源清理、异常日志记录
🔁 执行流程:代码语言:javascript复制DispatcherServlet → preHandle → Controller → postHandle → View Render → afterCompletion → Response3.2 Spring Boot 中使用 Interceptor✅ 创建 Interceptor代码语言:java复制public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String uri = request.getRequestURI();
System.out.println("【前置拦截】请求路径: " + uri);
// 模拟登录检查
HttpSession session = request.getSession();
if (session.getAttribute("user") == null && uri.startsWith("/admin")) {
response.sendRedirect("/login");
return false; // 拦截
}
return true; // 放行
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
modelAndView.addObject("currentTime", new Date());
}
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
if (ex != null) {
System.out.println("【异常】请求发生异常: " + ex.getMessage());
}
}
}✅ 注册 Interceptor代码语言:java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/admin/**", "/user/**") // 拦截路径
.excludePathPatterns("/login", "/public/**"); // 排除路径
}
}3.3 Interceptor 的典型应用场景场景
示例
权限控制
登录验证、角色权限校验
性能监控
记录 Controller 执行时间
操作日志
记录用户关键操作(如删除、修改)
国际化
根据请求头设置 Locale
接口幂等性
结合 Token 防止重复提交
四、Filter vs Interceptor:全方位对比对比维度
Filter
Interceptor
所属规范
Servlet 规范(J2EE)
Spring MVC 框架
依赖框架
❌ 不依赖 Spring
✅ 必须在 Spring 环境中使用
拦截范围
所有请求(包括静态资源、JSP)
仅 DispatcherServlet 映射的请求(Controller)
执行顺序
在 Servlet 之前执行
在 Controller 之前/之后执行
方法数量
1 个 doFilter()
3 个:preHandle、postHandle、afterCompletion
可获取对象
ServletRequest、ServletResponse
HttpServletRequest、HttpServletResponse、HandlerMethod、ModelAndView
对静态资源拦截
✅ 可以
❌ 默认不拦截(除非 DispatcherServlet 映射 /*)
异常处理
只能捕获 Filter 内部异常
afterCompletion 可捕获 Controller 异常
执行顺序优先级
更早(在 Spring 上下文之前)
稍晚(在 Spring MVC 调度之后)
性能开销
较低(原生 API)
稍高(Spring 反射调用)
五、实战选择指南:什么时候用哪个?✅ 优先使用 Filter 的场景:场景
原因
统一字符编码
需要在请求进入 Servlet 前就设置编码
跨域处理(CORS)
需要处理 OPTIONS 预检请求,早于 Spring MVC
安全过滤(XSS、SQL 注入)
需要对所有输入进行预处理
Gzip 压缩
需要包装 ServletResponse
非 Spring 环境
如纯 Servlet 应用、Filter 链
✅ 优先使用 Interceptor 的场景:场景
原因
登录状态校验
可获取 HttpSession 和 Spring Bean
权限控制
可结合 @PreAuthorize、SecurityContextHolder
性能监控
可精确统计 Controller 执行时间
操作日志记录
可获取 HandlerMethod,知道调用的是哪个方法
模型数据增强
可在 postHandle 中向 ModelAndView 添加数据
六、黄金组合:Filter + Interceptor 协同作战在实际项目中,两者往往配合使用,各司其职:
代码语言:javascript复制Client
↓
[Filter: 统一编码、CORS、安全过滤]
↓
[Filter: Gzip 压缩、日志记录]
↓
DispatcherServlet
↓
[Interceptor: 登录验证]
↓
[Interceptor: 权限校验]
↓
[Interceptor: 性能监控]
↓
Controller
↓
[Interceptor: afterCompletion 记录日志]
↓
[Filter: 响应压缩、日志]
↓
Client✅ 经典组合示例:
Filter:负责 UTF-8 编码、CORS、XSS 过滤Interceptor:负责 登录验证、权限控制、操作日志
七、面试高频题1. Filter 和 Interceptor 的区别?从规范、依赖、拦截范围、执行时机、方法数量等维度回答。
2. Filter 能拦截静态资源吗?Interceptor 呢?Filter 可以;Interceptor 默认不能(除非 DispatcherServlet 映射 /*)。
3. 如何让 Interceptor 拦截所有请求(包括静态资源)?修改 DispatcherServlet 的 url-pattern 为 /*,但需注意性能影响。
4. Filter 的 chain.doFilter() 有什么作用?调用下一个 Filter 或目标资源,是实现链式调用的关键。
5. Interceptor 的 afterCompletion 一定会执行吗?是的,即使 preHandle 返回 false 或发生异常,只要进入了 preHandle,afterCompletion 就会执行。
八、总结:Filter 与 Interceptor 的“黄金搭档”角色
Filter
Interceptor
定位
容器层“守门人”
框架层“执法官”
优势
通用、底层、不依赖框架
精细、灵活、可获取 Spring 上下文
劣势
功能单一、无法获取 Spring Bean
仅限 Spring MVC 请求
最佳实践
处理通用、底层问题
处理业务、安全、监控逻辑
✅ 终极建议:
Filter 做“通用处理”:编码、安全、日志、压缩Interceptor 做“业务拦截”:权限、监控、日志增强二者结合,构建完整拦截体系
友情链接:
Copyright © 2022 国战手游研发活动站 All Rights Reserved.