概念
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,其主要目的是将请求的发送者和接收者解耦。这种模式创建了一系列处理器对象,每个处理器都有一个对应的处理逻辑。当一个请求到来时,这些处理器按照顺序处理请求,直到其中一个处理器成功处理请求为止。
组成角色
- 抽象处理器(Handler):定义了一个处理请求的接口,包含一个指向下一个处理器的引用。
- 具体处理器(ConcreteHandler):实现抽象处理器接口,执行具体的处理逻辑,并决定请求是否传递给下一个处理器。
- 客户端(Client):负责创建处理器链,并向处理器链发送请求。
相关图示
示例代码
//定义抽象处理器(Handler)
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(String request);
}
//定义具体处理器(ConcreteHandler) HandlerA、HandlerB、HandlerC
class HandlerA extends Handler {
@Override
public void handleRequest(String request) {
if ("A".equals(request)) {
System.out.println("Handler A is processing the request");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class HandlerB extends Handler {
@Override
public void handleRequest(String request) {
if ("B".equals(request)) {
System.out.println("Handler B is processing the request");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class HandlerC extends Handler {
@Override
public void handleRequest(String request) {
if ("C".equals(request)) {
System.out.println("Handler C is processing the request");
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
//客户端代码
public class Client {
public static void main(String[] args) {
/**客户端创建了三个具体处理器,并将它们连接成一个处理器链。当客户端向处理器链发送请求时,处理器会按照顺序处理请求,直到其中一个处理器成功处理请求为止。**/
// 创建处理器对象
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
Handler handlerC = new HandlerC();
// 构建处理器链
handlerA.setNextHandler(handlerB);
handlerB.setNextHandler(handlerC);
// 发送请求
handlerA.handleRequest("A");
handlerA.handleRequest("B");
handlerA.handleRequest("C");
handlerA.handleRequest("D");
}
}
框架中的应用
拦截器链(Interceptor Chain):在Spring MVC框架中,当请求经过过滤器链处理并到达Servlet之后,请求会被传递给DispatcherServlet。DispatcherServlet的主要职责是将请求分发给适当的处理器(如Controller方法)。
Spring MVC中拦截器的执行流程:
- 请求到达
DispatcherServlet
。 DispatcherServlet
根据请求获取处理器(Handler)和拦截器链(Interceptor Chain)。DispatcherServlet
遍历拦截器链,依次执行拦截器的preHandle
方法。如果某个拦截器的preHandle
方法返回false
,则中止后续拦截器和处理器的执行,并立即返回响应。preHandle
方法通常用于执行请求预处理逻辑,例如身份验证和授权检查。- 如果所有拦截器的
preHandle
方法都返回true
,则DispatcherServlet
执行处理器(Handler)来处理请求。 - 处理器处理完请求后,
DispatcherServlet
再次遍历拦截器链,按照相反的顺序依次执行拦截器的postHandle
方法。postHandle
方法在处理器执行之后、视图渲染之前调用,通常用于添加模型属性或对请求进行后处理。 - 最后,
DispatcherServlet
渲染视图并返回响应。 - 在请求处理完成并且视图渲染完成之后,
DispatcherServlet
再次遍历拦截器链,按照相反的顺序依次执行拦截器的afterCompletion
方法。afterCompletion
方法通常用于清理资源和记录日志等操作。
抽象拦截处理器(Handler)
public interface HandlerInterceptor {
boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
处理器执行链(HandlerChain)
public class HandlerExecutionChain {
private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
// 处理器对象
private final Object handler;
// 拦截器数组
private HandlerInterceptor[] interceptors;
// 拦截器列表
private List<HandlerInterceptor> interceptorList;
// 当前处理的拦截器索引
private int interceptorIndex;
public HandlerExecutionChain(Object handler) {
this(handler, (HandlerInterceptor[]) null);
}
public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
this.interceptorIndex = -1;
if (handler instanceof HandlerExecutionChain) {
HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
this.handler = originalChain.getHandler();
this.interceptorList = new ArrayList();
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
} else {
this.handler = handler;
this.interceptors = interceptors;
}
}
public void addInterceptor(HandlerInterceptor interceptor) {
this.initInterceptorList().add(interceptor);
}
public void addInterceptors(HandlerInterceptor... interceptors) {
if (!ObjectUtils.isEmpty(interceptors)) {
this.initInterceptorList().addAll(Arrays.asList(interceptors));
}
}
private List<HandlerInterceptor> initInterceptorList() {
if (this.interceptorList == null) {
this.interceptorList = new ArrayList();
if (this.interceptors != null) {
this.interceptorList.addAll(Arrays.asList(this.interceptors));
}
}
this.interceptors = null;
return this.interceptorList;
}
public HandlerInterceptor[] getInterceptors() {
if (this.interceptors == null && this.interceptorList != null) {
this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
}
return this.interceptors;
}
// 执行拦截器链中的preHandle方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
// 执行拦截器链中的postHandle方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = this.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);
}
}
}
// 触发拦截器链中的afterCompletion方法
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.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 var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
}
}
适用场景:
- 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时,可以使用责任链模式。
- 当必须按顺序执行多个处理者时,可以使用该模式。
- 如果所需处理者及其顺序必须在运行时进行改变,可以使用责任链模式。
以下是一些责任链设计模式的典型应用场景:
- 日志记录:不同级别的日志消息可以由不同的日志处理器处理,例如,DEBUG、INFO、WARNING和ERROR级别的日志分别由不同的处理器处理。
- 权限验证:根据用户的权限和角色对请求进行多层次的验证。例如,先验证用户身份,然后验证用户是否有访问特定资源的权限。
- 请求过滤:在Web应用中,可以使用责任链模式实现请求过滤器,对请求进行预处理(如身份验证、数据验证等)和后处理(如添加响应头、日志记录等)。
- 事件处理:在图形用户界面(GUI)中,事件可以由多个处理器处理,如按钮点击、键盘输入等。责任链模式可以实现事件处理的优先级和顺序。