相对官方解释:将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这
些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止
个人理解: 实际就是当我有些需求比如对字符串作敏感词过滤,如果当前字符串满足某个敏感词或者某个处理逻辑,就不再继续执行下去,否则继续执行下去。当然责任链的变种也特别常用,就是类似一个字符串的处理逻辑,满足了一也会继续走下去。如果不使用设计模式你可能就是写一堆的if else 每次需要添加新的逻辑也是需要改变代码,让代码整体可维护性不强,如果使用责任链模式后,我们每次调整执行算法只需要添加新的执行器即可,就像我们再使用SpringMVC添加过滤器一样,我们不需要改变其他任何代码,仅仅只需要实现HandlerInterceptor接口即可
这里使用一种相对简单好理解的实现方法
首先抽象出一个处理抽象接口,所有处理器都必须实现该处理器的处理方法
public interface IHandler {
/**
* 所有子类实现该处理方法
* @return
*/
boolean handle();
}
然后就是各种各样的处理器
public class HandlerA implements IHandler{
@Override
public boolean handle() {
// 处理逻辑
System.out.println("处理器A开始处理了");
return false;
}
}
public class HandlerB implements IHandler{
@Override
public boolean handle() {
// 处理逻辑
System.out.println("处理器B开始处理了");
return true;
}
}
public class HandlerC implements IHandler{
@Override
public boolean handle() {
// 处理逻辑
System.out.println("处理器C开始处理了");
return false;
}
}
这里我们故意让 HandlerB 处理成功,这样演示效果就是HandlerC 不会被执行。
最后看看关键的 HandlerChain 实现
public class HandlerChain {
private List<IHandler> handlers = new ArrayList<>();
/**
* 添加处理器
* @param handler
*/
public void addHandler(IHandler handler) {
this.handlers.add(handler);
}
/**
* 执行处理
*/
public void handle() {
for (IHandler handler : handlers) {
boolean handled = handler.handle();
if (handled) {
break;
}
}
}
}
用一个 handlers 存储所有的执行器,然后遍历循环执行,如果遇到执行成功的,则返回不在继续执行
public class Test{
public static void main(String[] args) {
HandlerChain handlerChain = new HandlerChain();
handlerChain.addHandler(new HandlerA());
handlerChain.addHandler(new HandlerB());
handlerChain.addHandler(new HandlerC());
handlerChain.handle();
}
}
我们来看看SpringMvC中拦截器的应用
在springboot中我们要定义自定义拦截器其实很简单
public class TestInterceptor 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, @Nullable ModelAndView modelAndView) throws Exception {
System.out.println("拦截发送给客户端的请求");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
System.out.println("这里总是被执行");
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/wx/**", "/store/**", "/merchant/**", "/admin/**");
}
}
我们来看看实际执行拦截器的代码。在 HandlerExecutionChain 这个类中
可以看到也是用一个HandlerInterceptor[]数组去保存所有注册的拦截器,然后遍历调用的。由于这里是讲设计模式所以不对源码作过多研究,感兴趣的小伙伴可以自己去研究
看懂责任链模式很简单,实际要运用到项目和生产中还是要有相应的变化,比如可能会在 IHandler中做一个通用适配器的方法,满足适配器方法才会执行,然后所有处理器都必须执行,大致伪代码是这样的
for (IHandler handler : handlers) {
if (handler.adapter(s)) {
handler.handle();
}
}
业务是千变万化的,要更具实际需求选用合适的设计模式加一变形,满足自己复杂的业务,像我实际用到责任链模式也是做了好多改动类似,上面加了适配器,然后就是下一个处理器依赖于上一个处理器的结果集,种种都需要我们灵活运用,其实责任链模式还用另外的用类似链表的方式实现,只是个人感觉可读性不算特别好,所以这里没有给出这种实现,感兴趣的小伙伴可以自行了解