设计模式-行为型-职责链模式

  1. 1. 原理与实现
    1. 1.1 使用链表实现HandlerChain
    2. 1.2 使用数组实现HandlerChain
  2. 2. 过滤器、拦截器的实现
    1. 2.1 Servlet Filter
    2. 2.2 Spring Interceptor

1. 原理与实现

  • 职责链模式
    • Chian of Responsibility Design Pattern
    • Avoid coupling the sender of a request to its receiver by giving more than one object a chance to hadle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
    • 将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止
    • 在职责链模式当中,多个处理器依次处理同一个请求,一个请求先经过A处理器处理,再把请求传递给B处理器,B处理器处理完以后再传递给C处理器。各个处理器之间形成了一个链条,链条上的每个处理器各自承担各自的处理职责,所以叫做职责链模式。

1.1 使用链表实现HandlerChain

  • Handler是所有处理器的抽象父类
  • handle()是抽象方法
  • 每个具体的处理器类的handle()函数结构会比较类似,如果能处理请求,则进行处理;如果不能,则交由后面的处理器来进行处理
  • HandlerChain是处理器链,从数据结构来看,是一个记录了链头、链尾的链表。

public abstract class Handler {
protected Handler successor = null;

public void setSuccessor(Handler successor) {
this.successor = successor;
}

public final void handle() {
boolean handled = doHandle();

if (successor != null && !handled) {
    successor.handle();
}

}
public abstract boolean doHandle();
}

public class HandlerA extends Handler {
@Override
public void doHandle() {
boolean handled = false;
//…
return handled;
}
}

public class HandlerB extends Handler {
@Override
public void doHandle() {
boolean handled = false;
//…
return handled;
}
}

public class HandlerChain {
private Handler head = null;
private Handler tail = null;

public void addHandler(Handler handler) {
handler.setSuccessor(null);

if (head == null) {
  head = handler;
  tail = handler;
  return;
}

tail.setSuccessor(handler);
tail = handler;

}

public void handle() {
if (head != null) {
head.handle();
}
}
}

// 使用举例
public class Application {
public static void main(String[] args) {
HandlerChain chain = new HandlerChain();
chain.addHandler(new HandlerA());
chain.addHandler(new HandlerB());
chain.handle();
}
}

1.2 使用数组实现HandlerChain

public interface IHandler {
  boolean handle();
}

public class HandlerA implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerB implements IHandler {
  @Override
  public boolean handle() {
    boolean handled = false;
    //...
    return handled;
  }
}

public class HandlerChain {
  private List<IHandler> handlers = new ArrayList<>();

  public void addHandler(IHandler handler) {
    this.handlers.add(handler);
  }

  public void handle() {
    for (IHandler handler : handlers) {
      boolean handled = handler.handle();
      if (handled) {
        break;
      }
    }
  }
}

// 使用举例
public class Application {
  public static void main(String[] args) {
    HandlerChain chain = new HandlerChain();
    chain.addHandler(new HandlerA());
    chain.addHandler(new HandlerB());
    chain.handle();
  }
}

2. 过滤器、拦截器的实现

职责链模式最长建的使用位置是在框架的开发当中,比如过滤器和拦截器。

2.1 Servlet Filter

  • 实现堆HTTP请求的过滤功能

    • 鉴权
    • 限流
    • 记录日志
    • 验证参数等
  • 在实际使用当中,定义一个实现javax.servlet.Filter接口的过滤器类,并且将其配置在web.xml配置文件当中。Web容器启动的时候,会读取web.xml中的配置,创建过滤器对象。

  • 当有请求到来的时候,就会先经过过滤器,然后经由Servlet来进行处理

public class LogFilter implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    // 在创建Filter时自动调用,
    // 其中filterConfig包含这个Filter的配置参数,比如name之类的(从配置文件中读取的)
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("拦截客户端发送来的请求.");
    chain.doFilter(request, response);
    System.out.println("拦截发送给客户端的响应.");
  }

  @Override
  public void destroy() {
    // 在销毁Filter时自动调用
  }
}

// 在web.xml配置文件中如下配置:
<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>com.xzg.cd.LogFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>logFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
  • FilterChain的实现
public final class ApplicationFilterChain implements FilterChain {
  private int pos = 0; //当前执行到了哪个filter
  private int n; //filter的个数
  private ApplicationFilterConfig[] filters;
  private Servlet servlet;

  @Override
  public void doFilter(ServletRequest request, ServletResponse response) {
    if (pos < n) {
      ApplicationFilterConfig filterConfig = filters[pos++];
      Filter filter = filterConfig.getFilter();
      filter.doFilter(request, response, this);
    } else {
      // filter都处理完毕后,执行servlet
      servlet.service(request, response);
    }
  }

  public void addFilter(ApplicationFilterConfig filterConfig) {
    for (ApplicationFilterConfig filter:filters)
      if (filter==filterConfig)
         return;

    if (n == filters.length) {//扩容
      ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT];
      System.arraycopy(filters, 0, newFilters, 0, n);
      filters = newFilters;
    }
    filters[n++] = filterConfig;
  }
}

2.2 Spring Interceptor

有Spring MVC框架来提供实现,客户端发送的请求,会先经过Servlet Filter,然后在经过Spring Interceptor,最后再到达具体的业务代码当中。

// 代码实现
public class LogInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("拦截客户端发送来的请求.");
    return true; // 继续后续的处理
  }

  @Override
  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    System.out.println("拦截发送给客户端的响应.");
  }

  @Override
  public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    System.out.println("这里总是被执行.");
  }
}

//在Spring MVC配置文件中配置interceptors
<mvc:interceptors>
   <mvc:interceptor>
       <mvc:mapping path="/*"/>
       <bean class="com.xzg.cd.LogInterceptor" />
   </mvc:interceptor>
</mvc:interceptors>
  • Spring Interceptor底层实现
    • 基于职责链模式
    • 使用HandlerExecutionChain来处理
public class HandlerExecutionChain {
 private final Object handler;
 private HandlerInterceptor[] interceptors;

 public void addInterceptor(HandlerInterceptor interceptor) {
  initInterceptorList().add(interceptor);
 }

 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = 0; i < interceptors.length; i++) {
    HandlerInterceptor interceptor = interceptors[i];
    if (!interceptor.preHandle(request, response, this.handler)) {
     triggerAfterCompletion(request, response, null);
     return false;
    }
   }
  }
  return true;
 }

 void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = interceptors.length - 1; i >= 0; i--) {
    HandlerInterceptor interceptor = interceptors[i];
    interceptor.postHandle(request, response, this.handler, mv);
   }
  }
 }

 void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
   throws Exception {
  HandlerInterceptor[] interceptors = getInterceptors();
  if (!ObjectUtils.isEmpty(interceptors)) {
   for (int i = this.interceptorIndex; i >= 0; i--) {
    HandlerInterceptor interceptor = interceptors[i];
    try {
     interceptor.afterCompletion(request, response, this.handler, ex);
    } catch (Throwable ex2) {
     logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
    }
   }
  }
 }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com

文章标题:设计模式-行为型-职责链模式

文章字数:1.4k

本文作者:Leilei Chen

发布时间:2020-07-12, 09:22:10

最后更新:2020-07-16, 12:33:00

原始链接:https://www.llchen60.com/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F-%E8%A1%8C%E4%B8%BA%E5%9E%8B-%E8%81%8C%E8%B4%A3%E9%93%BE%E6%A8%A1%E5%BC%8F/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏