设计模式学习笔记(十四)责任链模式实现以及在Filter中的应用
责任链模式(Chain Of Responsibility Design Pattern),也叫做职责链,是将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
文章图片
一、责任链模式介绍
其实在日常生活中,有不少使用责任链的场景。比如公司采购审批流程,需要各个部门领导的批准同意。在责任链模式中,客户端只需要将请求发送到责任链上,无须关心请求的处理细节和传递,请求会自动进行传递。
1.1 责任链模式的结构
责任链模式的结构大致如下所示:
文章图片
abstract Handler
:抽象处理者,定义一个处理请求的接口,内部包含抽象处理方法和后继具体处理者Handler1、Handler2
:具体处理者,具体实现抽象处理者的方法,并对请求做一些逻辑处理Client
:客户端,使用职责链模式
根据上面的类图,可以实现如下代码:
/**
* @description: 抽象处理类
* @author: wjw
* @date: 2022/4/4
*/
public abstract class Handler {private Handler successor;
public Handler getSuccessor() {
return successor;
}public void setSuccessor(Handler successor) {
this.successor = successor;
}/**
* 处理请求的抽象方法
* @param request 请求
*/
public abstract void handleRequest(String request);
}
/**
* @description: 具体处理者1
* @author: wjw
* @date: 2022/4/4
*/
public class Handler1 extends Handler{private String handler;
public Handler1(String handler) {
this.handler = handler;
}@Override
public void handleRequest(String request) {
if ("handler1".equals(request)) {
System.out.println("具体处理者handler1进行请求处理");
} else {
if (getSuccessor() != null) {
//如果指向下一个具体处理者
getSuccessor().handleRequest(request);
} else {
System.out.println("没有处理者进行处理");
}
}
}
}
/**
* @description: 具体处理者2
* @author: wjw
* @date: 2022/4/4
*/
public class Handler2 extends Handler{private String handler;
public Handler2(String handler) {
this.handler = handler;
}@Override
public void handleRequest(String request) {
if ("handler2".equals(request)) {
System.out.println("具体处理者handler2进行请求处理");
} else {
if (getSuccessor() != null) {
getSuccessor().handleRequest(request);
} else {
System.out.println("请求没有被任何处理者处理");
}
}
}
}
/**
* @description: 客户端类
* @author: wjw
* @date: 2022/4/4
*/
public class Client {
public static void main(String[] args) {
Handler handler1 = new Handler1("handler1");
Handler handler2 = new Handler2("handler2");
handler1.setSuccessor(handler2);
handler1.handleRequest("handler1");
handler1.handleRequest("handler2");
}
}
测试结果:
具体处理者handler1进行请求处理
具体处理者handler2进行请求处理
二、责任链模式的应用场景 职责链模式最常见的应用就是用来开发各种框架的过滤器和拦截器,比如Spring Interceptor和Servlet Filter
2.1 在Servlet Filter中的应用
Filter 可以实现对HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等等。比如一些Servlet 容器(TomCat、Jetty等)就支持Filter的过滤功能。以TomCat 为例:
文章图片
所以当Servlet 请求到来时,首先会经过Filter 处理,最后再到达Servlet实例。我这里选取的TomCat版本是SpringBoot自带的9.0,先来看看
FilterChain
的接口:public interface FilterChain {
//Filter具体实现
void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}
ApplicationFilterChain
是责任链模式的具体实现类:public final class ApplicationFilterChain implements FilterChain {
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//Filter配置数组
private int pos = 0;
//执行Filter的序号
private int n = 0;
//目前Filter的个数
private Servlet servlet = null;
public ApplicationFilterChain() {
} @Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
//Filter 具体实现
//...
}public static ServletRequest getLastServicedRequest() {
return (ServletRequest)lastServicedRequest.get();
}public static ServletResponse getLastServicedResponse() {
return (ServletResponse)lastServicedResponse.get();
}void addFilter(ApplicationFilterConfig filterConfig) {
ApplicationFilterConfig[] newFilters = this.filters;
int var3 = newFilters.length;
for(int var4 = 0;
var4 < var3;
++var4) {
ApplicationFilterConfig filter = newFilters[var4];
if (filter == filterConfig) {
return;
}
}
//增加Filter
if (this.n == this.filters.length) {
newFilters = new ApplicationFilterConfig[this.n + 10];
System.arraycopy(this.filters, 0, newFilters, 0, this.n);
this.filters = newFilters;
}this.filters[this.n++] = filterConfig;
}
}
2.2 在Spring Interceptor中的应用
和Servlet Filter类似,在Spring 中也有对应的过滤器 Interceptor。它是由Spring MVC 框架来实现,借一张来自《设计模式之美》的图片来说明:
文章图片
客户端发送请求,首先会经过Servlet Filter,然后再经过Spring Interceptor,最后再到达具体的业务中。
和Filter一样,Interceptor 中也是基于责任链模式来实现的,与之相对的
HandlerInterceptor
是抽象处理接口:public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
会有各种具体处理类的实现:
文章图片
此外在其他框架中也存在着职责链模式的使用,比如Dubbo Filter、Netty ChannelPipeline等等
三、责任链模式实战 模拟在618大促期间的业务系统上线审批流程场景:
像是这些?线电商类的互联?公司,阿?、京东、拼多多等,在618期间都会做?些运营活动场景以及 提供的扩容备战,就像过年期间百度的红包?样。但是所有开发的这些系统都需要陆续的上线,因为临 近618有时候也有?些紧急的调整的需要上线,但为了保障线上系统的稳定性是尽可能的减少上线的, 也会相应的增强审批?度。就像?级响应、?级响应?样。使用责任链模式可以将各个服务模块按照一、二、三级进行分离,每个级别可以像
?这审批的过程在随着特定时间点会增加不同级别的负责?加?,每个?就像责任链模式中的每?个核 ?点。对于研发并不需要关?具体的审批流程处理细节,只需要知道这个上线更严格,级别也更 ?,但对于研发?员来说同样是点击相同的提审按钮,等待审核。
文章图片
Filter
一样用Successor
下一个级别的方法进行调用。具体结构图如下(来自《重学Java设计模式》)文章图片
具体代码如下:
参考资料 《设计模式之美》
http://c.biancheng.net/view/4024.html
【设计模式学习笔记(十四)责任链模式实现以及在Filter中的应用】《重学Java设计模式》
推荐阅读
- CommonsCollection7反序列化链学习
- 数学笔记
- Java学习笔记(韩顺平教育|Java学习笔记(韩顺平教育 b站有课程)
- Coursera|Coursera 学习笔记|Machine Learning by Standford University - 吴恩达
- 深入学习springCloud——服务注册中心之eureka
- 学习|java-->方法案例(公司迟到措施)
- 算法笔记|HDU - 2041 超级楼梯 (简单DP)
- 数据结构学习指导|数据结构初阶(八大排序)
- 机器学习算法系列(二十)-梯度提升决策树算法(Gradient Boosted Decision Trees / GBDT)
- 李宏毅机器学习课程|李宏毅机器学习课程笔记4(CNN、Why Deep、Semi-supervised)