全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

拦截器执行顺序

SpringMVC拦截器通过HandlerExecutionChain实现责任链模式,执行顺序严格遵循特定规则。

拦截器接口

Java
public interface HandlerInterceptor {
    default boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            Exception ex) throws Exception {
    }
}

执行顺序规则

方法执行时机执行顺序说明
preHandleHandler执行前正序(1→2→3)任一返回false则终止
postHandleHandler执行后逆序(3→2→1)视图渲染前
afterCompletion视图渲染后逆序(3→2→1)始终执行(类似finally)

源码实现

HandlerExecutionChain核心逻辑

Java
public class HandlerExecutionChain {
    private final Object handler;
    private final List<HandlerInterceptor> interceptorList = new ArrayList<>();

    // preHandle - 正序执行
    boolean applyPreHandle(HttpServletRequest request,
                           HttpServletResponse response) {
        for (int i = 0; i < interceptorList.size(); i++) {
            HandlerInterceptor interceptor = interceptorList.get(i);
            if (!interceptor.preHandle(request, response, this.handler)) {
                // 触发已执行拦截器的afterCompletion
                triggerAfterCompletion(request, response, null);
                return false;
            }
            this.interceptorIndex = i; // 记录执行位置
        }
        return true;
    }

    // postHandle - 逆序执行
    void applyPostHandle(HttpServletRequest request,
                         HttpServletResponse response, ModelAndView mv) {
        for (int i = interceptorList.size() - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptorList.get(i);
            interceptor.postHandle(request, response, this.handler, mv);
        }
    }

    // afterCompletion - 逆序执行
    void triggerAfterCompletion(HttpServletRequest request,
            HttpServletResponse response, Exception ex) {
        // 只执行preHandle成功的拦截器
        for (int i = this.interceptorIndex; i >= 0; i--) {
            HandlerInterceptor interceptor = interceptorList.get(i);
            interceptor.afterCompletion(request, response, this.handler, ex);
        }
    }
}

DispatcherServlet调用流程

Java
protected void doDispatch(HttpServletRequest request,
                          HttpServletResponse response) {
    HandlerExecutionChain mappedHandler = null;

    try {
        ModelAndView mv = null;

        // 1. 获取Handler执行链
        mappedHandler = getHandler(processedRequest);

        // 2. preHandle - 正序执行
        if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return; // 某个拦截器返回false,终止请求
        }

        // 3. 执行Handler
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

        // 4. postHandle - 逆序执行
        mappedHandler.applyPostHandle(processedRequest, response, mv);

        // 5. 渲染视图
        processDispatchResult(processedRequest, response, mappedHandler, mv, null);

    } catch (Exception ex) {
        // 异常时触发afterCompletion
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    }
}

执行顺序图解

Java
请求 → Interceptor1.preHandle
     → Interceptor2.preHandle
     → Interceptor3.preHandle
     → Handler执行
     → Interceptor3.postHandle
     → Interceptor2.postHandle
     → Interceptor1.postHandle
     → 视图渲染
     → Interceptor3.afterCompletion
     → Interceptor2.afterCompletion
     → Interceptor1.afterCompletion
     → 响应

异常场景处理

preHandle返回false

Java
// 假设Interceptor2返回false
请求  Interceptor1.preHandle(true)
      Interceptor2.preHandle(false)
      Interceptor1.afterCompletion // 只执行已成功的
      响应(不进入Handler)

Handler抛出异常

Java
// Handler执行异常时
请求  所有preHandle(true)
      Handler执行  异常!
      postHandle不执行
      视图不渲染
      所有afterCompletion执行(逆序带异常参数)
      异常处理

拦截器配置示例

text
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/**")
                .order(1); // 顺序

        registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**")
                .order(2);

        registry.addInterceptor(new CacheInterceptor())
                .addPathPatterns("/**")
                .order(3);
    }
}

preHandle顺序决定拦截优先级,afterCompletion保证资源清理始终执行。

要点总结

  1. preHandle正序执行,任一返回false则终止链条
  2. postHandle逆序执行,视图渲染前处理
  3. afterCompletion逆序执行,类似finally保证资源清理
  4. interceptorIndex记录preHandle成功位置,用于afterCompletion范围控制
  5. 异常时postHandle不执行,但afterCompletion始终执行

jwdev/articles/SPRINGMVC/专家/MVC核心源码执行流程/MVC核心源码执行流程/拦截器执行顺序.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 异常处理机制
下一篇 → 请求参数绑定与校验
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库