一、责任链模式定义
责任链模式的定义如下:
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。(Avoid coupling the sender of a request to its receiver by givingmore than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.)
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的处理结果。其流程大体如下所示
举个例子:我买的一台打印机不知道为什么电脑无法识别,于是我打了官方客服电话询问该怎么办
我:你好,我打印机出了点问题,电脑无法识别这个打印机
客服A:你好,我这边是受理投诉的部门,无法解决该问题,稍后会转接到售后部门,请不要挂机
嘟嘟嘟...
客服B:你好,我这边是售后客服,请问有什么能帮到您?
我:你好,我打印机出了点问题,电脑无法识别这个打印机
客服B:您可能没有正确安装驱动,请到官网下载驱动后再看看是否正常识别。
我:好的,我试试。
在这个过程中,我先打了投诉部门的电话,投诉部门处理不了,则将电话转接到了售后部门,售后部门给了我解决方案,这就是一个责任链模式的经典案例。
二、源码中的责任链模式
1、javax.servlet.FilterChain
再开始研究责任链模式在FilterChain中的使用之前,先看下在SpringBoot中,过滤器我们是怎么使用的。
首先要定义一个过滤器,实现OncePerRequestFilter接口,形式上大体如下所示
@Slf4j
@AllArgsConstructor
public class AdminAuthFilter extends OncePerRequestFilter {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
//此方法返回false表示需要执行该过滤器逻辑,反之则不需要执行过滤器逻辑
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//过滤器业务逻辑
//最后,进入下一个过滤器
filterChain.doFilter(request, response);
}
}
我们都知道,FilterChain(过滤器链)是Java Web中的一个概念,用于按顺序执行一系列过滤器对请求进行处理。它是在Servlet容器中实现的一种机制,用于预处理和后处理请求以及响应。
那么filterChain.doFilter(request, response);
这个代码做了什么事情呢?
Undertow是和Tomcat一样,都是一种高性能的Servlet容器,在Undertow中,FilterChain的实现类是io.undertow.servlet.handlers.FilterHandler$FilterChainImpl
。
可以看到,该类维护了一个location
成员变量,初始值为0,它的作用是一个“游标”,用于遍历另外一个成员变量filters
,最关键的一段代码逻辑如下
每调用一次doFilter方法,location都会自增1,如果filters列表没有到末尾,则从filter列表中取下一个Filter尝试执行doFilter方法,很明显这里使用了责任链模式;如果filters列表遍历完,则执行next.handleRequest。嗯?怎么还有个next.handleRequest方法?
仔细分析下当前类,FilterChainImpl是一个private修饰的内部类,它在FilterHandler类中,我们看下这个类的定义
这个类很有意思,它本身也是另外一个责任链模式中的一个环节。。。好家伙,这还是大责任链模式+小责任链模式,其类图如下所示
END.
注意:本文归作者所有,未经作者允许,不得转载