【Spring】HandlerInterceptor解析

HandlerInterceptor 深度解析

一、核心方法

HandlerInterceptor 接口定义了三个核心方法,构成完整的请求生命周期拦截机制:

java 复制代码
public interface HandlerInterceptor {
    // 1. 请求预处理(Controller执行前)
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                             Object handler) throws Exception {
        return true; // 返回true继续流程,false中断请求
    }

    // 2. 请求后处理(Controller执行后,视图渲染前)
    default void postHandle(HttpServletRequest request, HttpServletResponse response, 
                           Object handler, ModelAndView modelAndView) throws Exception {}

    // 3. 请求完成回调(视图渲染后)
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                                Object handler, Exception ex) throws Exception {}
}

执行顺序 :多个拦截器时,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()中捕获并记录控制器抛出的异常

四、注意事项与最佳实践

⚠️ 关键注意事项

  1. 执行顺序控制

    • 拦截器执行顺序由注册顺序决定,可使用@Order注解调整优先级(值越小越先执行)
    • 外层拦截器的preHandle()返回false会阻止内层拦截器执行
  2. 与Filter的区别

    • HandlerInterceptor:运行于Spring MVC框架内,可访问Spring上下文,精准拦截Controller
    • Filter:基于Servlet规范,更底层,可拦截所有请求(包括静态资源)
  3. 与AOP的选型

    • HandlerInterceptor:适用于Web层全局请求处理
    • AOP:适用于业务方法级别的横切关注点(如事务、缓存)

✅ 最佳实践

  1. 保持可测试性:将核心业务逻辑抽出到独立的Service或工具类,避免拦截器成为"不可测试的黑盒"

    java 复制代码
    // 推荐做法
    if (!authService.checkPermission(user, request.getRequestURI())) {
        log.warn("无权限访问: {}", request.getRequestURI());
        response.sendRedirect("/403");
        return false;
    }
  2. 避免臃肿逻辑:不要在拦截器中编写大量业务判断代码

  3. 增强可观测性:为拦截器添加日志和Trace ID,便于分布式链路追踪和问题排查

  4. 异常处理结合 :配合@ControllerAdvice实现全局异常捕获与处理

  5. 资源及时释放 :必须在afterCompletion()中释放线程本地变量(ThreadLocal),防止内存泄漏


五、典型配置示例

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/ **")    // 拦截路径
                .excludePathPatterns("/api/login", "/api/public/ **"); // 排除路径
    }
}

通过合理运用HandlerInterceptor,可构建健壮的"请求防火墙",提升系统的安全性、可维护性与可扩展性。

相关推荐
明月_清风4 分钟前
用自然语言操控真机:Google Artemis 移动端 AI Agent 上手与实践
人工智能·后端
怪我冷i5 分钟前
Rust 的impl语法详解
开发语言·后端·rust
wuminyu27 分钟前
Java字节码学习总结:字节码如何加载、解析和执行
java·linux·c语言·jvm·c++
Flynn Liang1 小时前
大模型怎么自己调函数?Spring AI 2.0 Tool Calling 自动循环原理 + 完整时序图
java·人工智能·spring·agent·函数调用·springai·toolcalling
我就是全世界1 小时前
OpenCode Go 套餐划算吗:先看你用哪个模型
开发语言·后端·golang
乌暮2 小时前
请求进门先安检:Spring 拦截器与统一功能实战指南
java·开发语言·后端·学习·spring
学长毕设2 小时前
基于SpringBoot的烘焙商品商品系统-附源码
java·spring boot·后端
付威20232 小时前
Durable Execution 怎样设计:从运行记录到中断恢复
后端
金銀銅鐵3 小时前
[Java] 用纯 Swing 做一个《論語·學而》阅读器
java·ai编程·交互设计
艾伦_耶格宇3 小时前
【kubernetes - 1.28版本】-11 K8S核心组件
java·容器·kubernetes