HandlerInterceptor 深度解析
一、核心方法
HandlerInterceptor接口定义了三个核心方法,构成完整的请求生命周期拦截机制:
publicinterfaceHandlerInterceptor{// 1. 请求预处理(Controller执行前)defaultbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{returntrue;// 返回true继续流程,false中断请求}// 2. 请求后处理(Controller执行后,视图渲染前)defaultvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{}// 3. 请求完成回调(视图渲染后)defaultvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{}}执行顺序:多个拦截器时,preHandle()按配置顺序正序执行,而postHandle()和afterCompletion()按逆序执行。
二、主要作用
HandlerInterceptor的核心作用可归纳为:
1.请求预处理
在Controller方法执行前进行通用操作,如权限验证、日志记录、参数修改等。通过返回布尔值决定是否继续执行后续流程。
2.请求后处理
在Controller执行后、视图渲染前对ModelAndView对象进行操作,可修改模型数据或视图属性。
3.资源清理
在整个请求完成后(包括视图渲染)执行资源释放操作,如关闭文件流、释放数据库连接,防止资源泄漏。
三、应用场景
高频场景
| 场景 | 实现方式 | 典型方法 |
|---|---|---|
| 登录鉴权 | 检查Session/JWT令牌 | preHandle() |
| 接口限流 | 基于Redis计数器 | preHandle() |
| 日志追踪 | 生成TraceId并写入MDC | preHandle()+afterCompletion() |
| 参数加解密 | 对敏感参数统一处理 | preHandle() |
| 性能监控 | 记录请求耗时 | preHandle()+afterCompletion() |
| 多租户隔离 | 解析租户ID并设置上下文 | preHandle() |
特殊场景
- 跨域处理:动态添加CORS响应头
- 请求头统一处理:解析
Authorization、X-Request-ID等元数据 - 异常信息记录:在
afterCompletion()中捕获并记录控制器抛出的异常
四、注意事项与最佳实践
⚠️ 关键注意事项
执行顺序控制
- 拦截器执行顺序由注册顺序决定,可使用
@Order注解调整优先级(值越小越先执行) - 外层拦截器的
preHandle()返回false会阻止内层拦截器执行
- 拦截器执行顺序由注册顺序决定,可使用
与Filter的区别
- HandlerInterceptor:运行于Spring MVC框架内,可访问Spring上下文,精准拦截Controller
- Filter:基于Servlet规范,更底层,可拦截所有请求(包括静态资源)
与AOP的选型
- HandlerInterceptor:适用于Web层全局请求处理
- AOP:适用于业务方法级别的横切关注点(如事务、缓存)
✅ 最佳实践
保持可测试性:将核心业务逻辑抽出到独立的Service或工具类,避免拦截器成为"不可测试的黑盒"
// 推荐做法if(!authService.checkPermission(user,request.getRequestURI())){log.warn("无权限访问: {}",request.getRequestURI());response.sendRedirect("/403");returnfalse;}避免臃肿逻辑:不要在拦截器中编写大量业务判断代码
增强可观测性:为拦截器添加日志和Trace ID,便于分布式链路追踪和问题排查
异常处理结合:配合
@ControllerAdvice实现全局异常捕获与处理资源及时释放:必须在
afterCompletion()中释放线程本地变量(ThreadLocal),防止内存泄漏
五、典型配置示例
@ConfigurationpublicclassWebConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry.addInterceptor(newAuthInterceptor()).addPathPatterns("/api/ **")// 拦截路径.excludePathPatterns("/api/login","/api/public/ **");// 排除路径}}通过合理运用HandlerInterceptor,可构建健壮的"请求防火墙",提升系统的安全性、可维护性与可扩展性。