Skip to content

拦截器 (Interception) ​

所有的 HandlerMapping 实现都支持处理器拦截,这在你需要对请求应用横切关注点(Cross-cutting Concerns)时非常有用。

HandlerInterceptor 接口 ​

一个拦截器需要实现 org.springframework.web.servlet.HandlerInterceptor 接口,它包含三个主要的回调方法:

  • preHandle(..):在实际处理器运行之前调用。返回值是一个布尔值。如果返回 true,则继续执行链;如果返回 false,则中断执行链,处理器将不会被调用。
  • postHandle(..):在处理器运行之后调用。
  • afterCompletion(..):在整个请求完成后调用(即视图渲染完成后)。

注意

对于使用 @ResponseBody 或 ResponseEntity 的控制器方法,响应会在 HandlerAdapter 内部被写入并提交,这发生在 postHandle 调用之前。这意味着在 postHandle 中添加响应头已经太晚了。对于此类需求,请使用 ResponseBodyAdvice。

安全警告

拦截器并不适合作为核心安全层(Security Layer)。由于其路径匹配可能与注解控制器的路径匹配存在细微的不一致,可能会产生绕过风险。通常,我们强烈建议使用 Spring Security,或者基于 Servlet 过滤器的类似方法,并尽可能早地应用安全策略。


补充教学 ​

1. 过滤器 (Filter) vs 拦截器 (Interceptor) ​

这是 Spring MVC 开发者最常混淆的一点:

特性过滤器 (Servlet Filter)拦截器 (HandlerInterceptor)
所属规范Servlet 规范Spring MVC 框架
执行时机在 DispatcherServlet 处理之前/后在进入 Controller 之前/后
访问能力只能访问 Request/Response可以访问 Spring 上下文、Bean、以及具体的 Handler 对象
适用场景字符编码、敏感词过滤、通用安全业务权限校验、性能监控、模型属性注入

2. 执行顺序详解 ​

如果你有多个拦截器,它们的执行顺序如下(假设顺序为 A, B):

  1. Interceptor A.preHandle
  2. Interceptor B.preHandle
  3. Controller 业务逻辑
  4. Interceptor B.postHandle (逆序)
  5. Interceptor A.postHandle (逆序)
  6. 渲染视图
  7. Interceptor B.afterCompletion (逆序)
  8. Interceptor A.afterCompletion (逆序)

核心理解:preHandle 是顺序执行,而 postHandle 和 afterCompletion 是逆序执行(类似栈的结构)。

3. 如何解决 postHandle 无法修改 JSON 的问题? ​

如文档所述,当你的 Controller 返回 JSON 时,数据已经通过 Jackson 写进流里了。如果你非要对全局的响应 JSON 做修改(比如统一包装一个 code: 200):

  • 方案:实现 ResponseBodyAdvice<Object>。
  • 原理:它允许你在 Spring 真正把对象转成 JSON 字符串的一瞬间进行拦截和修改。

Based on Spring Framework.