Skip to content

拦截器 (Interception)

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

HandlerInterceptor 接口

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

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

注意

对于使用 @ResponseBodyResponseEntity 的控制器方法,响应会在 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 是顺序执行,而 postHandleafterCompletion 是逆序执行(类似栈的结构)。

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

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

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

Based on Spring Framework.