原理和实现

职责链模式的英文翻译是 Chain Of Responsibility Design Pattern

:::color3 什么是职责链模式?

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。 在职责链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作职责链模式。

:::

框架中常用的过滤器、拦截器

https://time.geekbang.org/column/article/217395

职责链模式常用在框架的开发中,为框架提供扩展点,让框架的使用者在不修改框架源码的情况下,基于扩展点添加新的功能。实际上,更具体点来说,职责链模式最常用来开发框架的过滤器和拦截器。

Servlet Filter

Servlet Filter 是 Java Servlet 规范中定义的组件,翻译成中文就是过滤器,它可以实现对 HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等等。

责任链模式 - 图1

ApplicationFilterChain 类就是 Tomcat 提供的 FilterChain 的实现类
  1. public final class ApplicationFilterChain implements FilterChain {
  2. private int pos = 0; //当前执行到了哪个filter
  3. private int n; //filter的个数
  4. private ApplicationFilterConfig[] filters;
  5. private Servlet servlet;
  6. @Override
  7. public void doFilter(ServletRequest request, ServletResponse response) {
  8. if (pos < n) {
  9. ApplicationFilterConfig filterConfig = filters[pos++];
  10. Filter filter = filterConfig.getFilter();
  11. filter.doFilter(request, response, this);
  12. } else {
  13. // filter都处理完毕后,执行servlet
  14. servlet.service(request, response);
  15. }
  16. }
  17. public void addFilter(ApplicationFilterConfig filterConfig) {
  18. for (ApplicationFilterConfig filter:filters)
  19. if (filter==filterConfig)
  20. return;
  21. if (n == filters.length) {//扩容
  22. ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
  23. System.arraycopy(filters, 0, newFilters, 0, n);
  24. filters = newFilters;
  25. }
  26. filters[n++] = filterConfig;
  27. }
  28. }

Spring Interceptor

责任链模式 - 图2Servlet Filter 是 Servlet 规范的一部分,实现依赖于 Web 容器。Spring Interceptor 是 Spring MVC 框架的一部分,由 Spring MVC 框架来提供实现。

  1. public class LogInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("拦截客户端发送来的请求.");
  5. return true; // 继续后续的处理
  6. }
  7. @Override
  8. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9. System.out.println("拦截发送给客户端的响应.");
  10. }
  11. @Override
  12. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  13. System.out.println("这里总是被执行.");
  14. }
  15. }
  16. //在Spring MVC配置文件中配置interceptors
  17. <mvc:interceptors>
  18. <mvc:interceptor>
  19. <mvc:mapping path="/*"/>
  20. <bean class="com.xzg.cd.LogInterceptor" />
  21. </mvc:interceptor>
  22. </mvc:interceptors>

Core J2EE Patterns: Intercepting Filter Pattern

https://www.informit.com/articles/article.aspx?p=1398619&seqNum=3

拦截器过滤器模式

Use an Intercepting Filter as a pluggable filter to pre and postprocess requests and responses. A filter manager combines loosely coupled filters in a chain, delegating control to the appropriate filter. In this way, you can add, remove, and combine these filters in various ways without changing existing code.

使用拦截过滤器作为可插拔过滤器来预处理和后处理请求和响应。Filter Manger将松散耦合的Filter组合在一个链中,将控制委派给相应的Filter。这样,您可以通过各种方式添加、删除和组合这些过滤器,而无需更改现有代码。

过滤器使用部署描述符以声明方式控制。 部署配置文件设置过滤器链,并且可以包含特定 URL 到此过滤器链的映射。当客户端请求与配置的 URL 映射匹配的资源时,将在调用请求的目标资源之前(预处理)和/或之后(后处理)调用链中的过滤器。

责任链模式 - 图3

责任链模式 - 图4

Client 客户

The Client sends a request to the FilterManager.
客户端向<font style="color:rgb(0, 0, 0);">FilterManager</font>发送请求。

FilterManager 过滤器管理器

The FilterManager manages filter processing. It creates the FilterChain with the appropriate filters, in the correct order, and initiates processing.
<font style="color:rgb(0, 0, 0);">FilterManager</font>管理过滤器处理。它以正确的顺序使用适当的过滤器创建过滤器链,并启动处理。

FilterChain 过滤器链

The FilterChain is an ordered collection of independent filters.
过滤器链是独立过滤器的有序集合。

FilterOne, FilterTwo

FilterOne and FilterTwo represent individual filters that are mapped to a Target. The FilterChain coordinates the processing of filters.
FilterOne 和 FilterTwo 表示映射到目标的各个过滤器。过滤器链协调过滤器的处理。

Target 目标

The Target is the resource requested by the client.
目标是客户端请求的资源。

责任链模式 - 图5

SpringBoot SecurityFilterChain

https://docs.spring.io/spring-security/reference/servlet/architecture.html

SecurityFilterChain is used by FilterChainProxy to determine which Spring Security Filter instances should be invoked for the current request.

The following image shows the role of SecurityFilterChain.

责任链模式 - 图6