责任链模式的定义是:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
说的更直白一些,在责任链模式中,多个处理器(也就是刚刚定义中说的“接收对象”)依次处理同一个请求。一个请求先经过 A 处理器处理,然后再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作责任链模式。
1.代码示例
下面来看个例子,公司处理员工请假请求
// 抽象处理者
public abstract class Handler {
// 当前领导能审批通过的最多天数
public int maxDay;
// 下一个 Handler
private Handler nextHandler;
// 构造 Handler 时需要传入批假假的最大填数
protected Handler(int maxDay) {
this.maxDay = maxDay;
}
// 处理请假请求
protected void handleRequest(int day) {
// 如果能够批假
if (day <= maxDay) {
reply(day);
} else {
// 审批权限不够,交给责任链上的下一个审批者
if (nextHandler != null) {
nextHandler.handleRequest(day);
} else {
System.out.println(day + "天请假,没有更高的领导审批了,不通过");
}
}
}
// 设置责任链中下一个处理请求的对象
public void setNextHandler(Handler handler) {
nextHandler = handler;
}
// 交由具体的handler来实现
protected abstract void reply(int day);
}
// 具体处理者-项目经理
public class ProjectManager extends Handler {
public ProjectManager(int maxDay) {
super(maxDay);
}
@Override
protected void reply(int day) {
System.out.println(day + "天请假,项目经理直接审批通过");
}
}
// 具体处理者-部门经理
public class DepartmentHead extends Handler {
public DepartmentHead(int maxDay) {
super(maxDay);
}
@Override
protected void reply(int day) {
System.out.println(day + "天请假,部门经理审批通过");
}
}
// client建立责任链处理请求
public class Client {
public static void main(String[] args) {
Handler handler1 = new ProjectManager(5);
Handler handler2 = new DepartmentHead(10);
handler1.setNextHandler(handler2);
// 总是从链式的首端发起请求
handler1.handleRequest(2);
handler1.handleRequest(3);
handler1.handleRequest(8);
handler1.handleRequest(12);
}
}
结果如下
2天请假,项目经理直接审批通过
3天请假,项目经理直接审批通过
8天请假,部门经理审批通过
12天请假,没有更高的领导审批了,不通过
PS:HandlerChain 除了使用链表结构,也可以使用数组来保存各个 Handler,然后在 在 HandlerChain 的 handle() 函数中,依次调用每个处理器的 handle() 函数。
2.源码应用
Spring Interceptor,翻译成中文就是拦截器,可以用来实现对 Http 请求的拦截处理
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse resp
System.out.println("拦截客户端发送来的请求.");
return true; // 继续后续的处理(若拦截就返回false)
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse respon
System.out.println("拦截发送给客户端的响应.");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse
System.out.println("这里总是被执行.");
}
}
// 在Spring MVC配置文件中配置interceptors
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.xzg.cd.LogInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
其中,HandlerExecutionChain 类是职责链模式中 的处理器链。HandlerExecutionChain 的源码如下所示,对代码也进行了一些简化,只保留了关键代码:
public class HandlerExecutionChain {
// 通过数组来保存所有的 Handler(HandlerInterceptor)
private HandlerInterceptor[] interceptors;
public void addInterceptor(HandlerInterceptor interceptor) {
initInterceptorList().add(interceptor);
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse respons
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历拦截器链,依次执行 HandlerInterceptor#preHandle()
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
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历拦截器链,依次执行 HandlerInterceptor#postHandle()
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 re
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
// 遍历拦截器链,依次执行 HandlerInterceptor#afterCompletion()
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);
}
}
}
}
}
在 Spring 框架中,DispatcherServlet 的 doDispatch() 方法来分发请求,它在真正的业务逻辑执行前后,执行 HandlerExecutionChain 中的 applyPreHandle() 和 applyPostHandle() 函数,用来实现拦截的功能。具体的代码实现很简单,我们都可以脑补出来,这里就不罗列了。
另外,Netty 也是基于责任链模式的无锁串行化编程,是通过链表组织所有 Handler(ChannelInBoundHandler、ChannelOutBoundHandler),感兴趣的同学可以自行去了解。
3.总结
在责任链模式中,多个处理器依次处理同一个请求。一个请求先经过 A 处理器处理,然后 再把请求传递给 B 处理器,B 处理器处理完后再传递给 C 处理器,以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作责任链模式。
在 GoF 的定义中,一旦某个处理器能处理这个请求,就不会继续将请求传递给后续的处理器了。当然,在实际的开发中,也存在对这个模式的变体,那就是请求不会中途终止传递, 而是会被所有的处理器都处理一遍。
职责链模式有两种常用的实现。一种是使用链表来存储处理器,另一种是使用数组来存储处理器,后面一种实现方式更加简单。
责任链模式常用在框架开发中,可以用来实现框架的过滤器、拦截器功能,让框架的使用者在不需要修改框架源码的情况下,添加新的过滤拦截功能。这也体现了之前讲到的对扩展开放、 对修改关闭的设计原则。






还没有评论,来说两句吧...