当前位置: 首页 > article >正文

Spring MVC拦截器中的责任链模式深度解析

一、责任链模式本质与Spring MVC拦截器的设计契合

1.1 责任链模式核心思想

责任链模式(Chain of Responsibility)是一种行为型设计模式,其核心在于将请求的发送者和接收者解耦,允许多个对象都有机会处理请求。典型的责任链模式包含三个关键角色:

  • Handler(抽象处理者):定义处理请求的接口

  • ConcreteHandler(具体处理者):实现具体处理逻辑

  • Client(客户端):组装处理链并触发请求

1.2 Spring MVC拦截器架构

Spring MVC拦截器的实现完美体现了责任链模式的设计思想:



二、Spring MVC拦截器链的源码级解析

2.1 HandlerExecutionChain核心源码

public class HandlerExecutionChain {
    private final List<HandlerInterceptor> interceptorList = new ArrayList<>();
    
    boolean applyPreHandle(HttpServletRequest request, 
                          HttpServletResponse response, 
                          Object handler) throws Exception {
        for (int i = 0; i < this.interceptorList.size(); i++) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            if (!interceptor.preHandle(request, response, handler)) {
                triggerAfterCompletion(request, response, handler, null);
                return false;
            }
            this.interceptorIndex = i;
        }
        return true;
    }
    
    void applyPostHandle(HttpServletRequest request,
                        HttpServletResponse response,
                        Object handler,
                        ModelAndView modelAndView) throws Exception {
        for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            interceptor.postHandle(request, response, handler, modelAndView);
        }
    }
}

2.2 拦截器链的三大执行阶段

  1. preHandle正向遍历执行(控制器方法前)

  2. postHandle逆向遍历执行(控制器方法后,视图渲染前)

  3. afterCompletion正向遍历执行(请求完成时,包括异常情况)


三、自定义拦截器链实现方案

3.1 基础拦截器实现

public class LogInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        log.info("请求开始: {} {}", request.getMethod(), request.getRequestURI());
        return true; // 继续执行链
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler, 
                               Exception ex) {
        long duration = System.currentTimeMillis() - 
                        (long) request.getAttribute("startTime");
        log.info("请求完成: {} 耗时{}ms", request.getRequestURI(), duration);
    }
}

3.2 高级链式配置

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthInterceptor())
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/login");
        
        registry.addInterceptor(new LogInterceptor())
                .order(Ordered.HIGHEST_PRECEDENCE);
        
        registry.addInterceptor(new PerformanceInterceptor())
                .order(Ordered.LOWEST_PRECEDENCE);
    }
}

四、责任链模式在拦截器中的典型应用场景

4.1 权限校验链


4.2 请求处理流水线

public class ProcessingChainInterceptor implements HandlerInterceptor {
    
    private List<RequestProcessor> processors = Arrays.asList(
        new ValidationProcessor(),
        new CachingProcessor(),
        new TransformationProcessor()
    );
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) {
        for (RequestProcessor processor : processors) {
            if (!processor.process(request)) {
                return false;
            }
        }
        return true;
    }
}

五、高级特性与最佳实践

5.1 拦截器链中断机制

public class CircuitBreakerInterceptor implements HandlerInterceptor {
    
    private CircuitBreaker circuitBreaker = new CircuitBreaker();
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        if (circuitBreaker.isOpen()) {
            response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value());
            return false; // 中断请求处理
        }
        return true;
    }
}

5.2 异步请求处理

public class AsyncInterceptor implements AsyncHandlerInterceptor {
    
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request,
                                             HttpServletResponse response,
                                             Object handler) {
        log.info("进入异步处理模式");
    }
}

5.3 性能优化建议

  1. 拦截器排序:高频拦截器靠前执行

  2. 避免阻塞操作:不在preHandle中进行IO密集型操作

  3. 缓存重复计算:利用ThreadLocal缓存跨拦截器数据

  4. 合理使用短路:及时中断无效请求


六、与过滤器(Filter)的责任链对比

对比维度拦截器(Interceptor)过滤器(Filter)
作用范围Spring MVC上下文Servlet容器级别
依赖关系需要Spring容器支持不依赖Spring
执行时机Controller方法前后请求进入DispatcherServlet前
访问对象可以获取Handler信息只能获取Servlet API对象
异常处理可以通过@ControllerAdvice处理需要通过web.xml配置错误页面

七、源码级调试技巧

7.1 关键断点设置

  1. DispatcherServlet#doDispatch

  2. HandlerExecutionChain#applyPreHandle

  3. AbstractHandlerMapping#getHandler

7.2 执行流程观察



八、企业级实践总结

8.1 设计原则

  1. 单一职责:每个拦截器专注一个功能点

  2. 开闭原则:新增功能通过添加拦截器实现

  3. 可配置化:通过配置文件管理拦截器开关

8.2 常见陷阱

  • 顺序依赖:错误配置拦截器执行顺序导致逻辑错误

  • 线程安全:错误使用成员变量引发并发问题

  • 性能黑洞:在拦截器中执行重量级操作影响吞吐量

  • 异常处理:未正确处理preHandle返回false的情况

8.3 最佳实践

// 使用组合模式封装多个校验器
public class CompositeValidatorInterceptor implements HandlerInterceptor {
    
    private List<RequestValidator> validators;
    
    @Override
    public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response,
                            Object handler) {
        return validators.stream()
               .allMatch(validator -> validator.validate(request));
    }
}

深度思考:尝试在拦截器中实现动态可配置的处理链,并通过管理界面实时调整拦截器顺序和开关状态。遇到技术难点欢迎在评论区交流讨论,觉得本文对你有帮助请点赞⭐收藏📌,关注获取更多Spring深度解析!


http://www.kler.cn/a/588059.html

相关文章:

  • 深度探索DeepSeek部署的安全底线
  • 第十五届蓝桥杯大赛软件赛省赛Python 大学 C 组题目试做(上)
  • vulnhub-Hackme-隧道建立、SQL注入、详细解题、思路清晰。
  • CSS:使用内边距时,解决宽随之改变问题
  • C#通过API接口返回流式响应内容---SSE方式
  • rk3568 yt8521S phy设备层丢包定位处理
  • Smart Time Plus smarttimeplus-MySQLConnection SQL注入漏洞(CVE-2024-53544)
  • 链表题目2(leetcode24题)交换链表里面的节点
  • Flutter FloatingActionButton 从核心用法到高级定制
  • 从LLM出发:由浅入深探索AI开发的全流程与简单实践(全文3w字)
  • ElasticSearch组合查询及实际应用
  • python unity通讯数据解析2
  • WindowsPE文件格式入门01.PE头
  • [Windows] OfficeScrubber_13--office卸载清理工具
  • 【JavaEE】快速上手JSON:构建高效 Java 后端数据桥梁,开启交互新篇,以 @RequestBody 为引的探索之旅
  • 类和对象C++ (未完:对象特征)
  • linux - 基础IO之操作与文件描述符全解析:从C语言到系统调用底层实现
  • python爬虫Scrapy(5)之增量式
  • 生物角度分析
  • PHP语言的死锁