springboot拦截器 preHandle / afterCompletion 执行规则说明

125

在 Spring Boot(Spring MVC)中,多个拦截器会按配置顺序依次执行。其核心流程如下:

拦截器执行顺序(preHandle → controller → postHandle → afterCompletion)

  1. 按顺序执行 preHandle()

    • 只要某个 preHandle() 返回 false:\ → 后续拦截器不再执行 preHandle\ → 控制器方法不会执行\ → 直接进入 已执行过 preHandle 的拦截器afterCompletion()\ → 顺序为 逆序执行

  2. 若所有 preHandle() 均返回 true

    • 执行 Controller

    • 执行 postHandle()(逆序)

    • 执行 afterCompletion()(逆序)


📌 关键结论

如果:

  • 第一个拦截器(Interceptor 1)preHandle() 返回 true

  • 第二个拦截器(Interceptor 2)preHandle() 返回 false

那么执行流程如下:

拦截器

preHandle

postHandle

afterCompletion

Interceptor 1

✔️ 执行

❌ 不执行

✔️ 会执行

Interceptor 2

✔️ 执行

❌ 不执行

✔️ 会执行

👉 第一个拦截器的 afterCompletion() 一定会被执行。


sequenceDiagram participant Client participant Interceptor1 participant Interceptor2 participant Controller Client ->> Interceptor1: preHandle() → true Interceptor1 ->> Interceptor2: preHandle() → false Note right of Interceptor2: 拦截请求<br/>不再继续后续流程 Interceptor2 ->> Interceptor1: afterCompletion() Interceptor1 ->> Client: 返回响应sequenceDiagram autonumber participant Client participant I1 as Interceptor 1 participant I2 as Interceptor 2 participant I3 as Interceptor 3 participant C as Controller rect rgb(235, 248, 255) Note over Client,C: 场景 A:全部通过 Client->>I1: preHandle() → true I1->>I2: preHandle() → true I2->>I3: preHandle() → true I3->>C: 调用控制器方法 C-->>I3: 返回,I3.postHandle() I3-->>I2: I2.postHandle() I2-->>I1: I1.postHandle() I1-->>I3: I3.afterCompletion() I3-->>I2: I2.afterCompletion() I2-->>I1: I1.afterCompletion() I1-->>Client: 响应 end rect rgb(255, 245, 230) Note over Client,C: 场景 B:中途拦截(I2 返回 false) Client->>I1: preHandle() → true I1->>I2: preHandle() → false Note right of I2: 终止调用链;不再调用 I3/Controller I2-->>I1: I2.afterCompletion() I1-->>Client: I1.afterCompletion() → 响应 end rect rgb(255, 235, 238) Note over Client,C: 场景 C:Controller 或渲染异常 Client->>I1: preHandle() → true I1->>I2: preHandle() → true I2->>I3: preHandle() → true I3->>C: 调用控制器方法 C--x I3: 抛异常(或视图渲染异常) Note right of I3: postHandle() 通常不执行 I3-->>I2: I3.afterCompletion() I2-->>I1: I2.afterCompletion() I1-->>Client: I1.afterCompletion() → 错误响应/全局异常处理 end