1.引子
责任链模式,应该说我们都比较熟悉了,比如说servlet规范中的过滤器(filter),再比如说springmvc中的拦截器(interceptor)。
既然大家都这么熟悉了,那么写这篇文章的意义在哪里呢?我们可以尝试思考这么几个问题
- 抛开框架提供的filter、interceptor,如果说我们自己就是框架开发者,该如何利用责任链模式,提供框架的扩展能力呢?
- 你知道filter、interceptor底层实现与执行机制吗?换句话说你看过它们的源码吗?
- 如果在项目中,同时存在filter、interceptor、甚至aop,你知道它们的执行顺序吗?
带着以上几个问题,我将通过这篇文章一并分享给你,期望通过本篇文章,你将获得
- 如何自己定义实现一个责任链模式
- 彻底搞清楚filter、interceptor实现原理
- 不再感到困惑项目中同时存在filter、interceptor、aop
2.案例
2.1.原汁原味责任链模式
从设计模式分类上,责任链模式是一种行为型设计模式,主要解决的是对象之间的交互问题。
通过责任链模式,可以很方便的实现提供代码复用与扩展能力,尤其是开发框架方面,支持用户在不修改框架源码的情况下,非常容易实现根据业务需要,从而扩展框架能力。
这里我用一段话给你描述责任链模式的执行机制,方便你理解,业务场景如下
- 有一个发送者发送请求
- 有一个接收者接收请求并处理请求
- 在发送者与接收者之间,需要一些预处理,比如说认证,授权等,认证与授权之间的事件有依赖关系,必须认证通过后,才会进一步处理授权
- 那么在发送者与接收者之间,我们可以增加处理器A负责认证、处理器B负责授权,请求只有经过处理器A认证通过后,再进一步通过处理器B授权处理
- 如果有更多的处理C/D......处理情形类似
- 你看到了,最终业务请求的处理路径是:发送者发出请求--->处理器A--->处理器B--->......--->接收者处理请求。这就是一条链,也是责任链模式的名称由来
理解了责任链模式,接下来我们来看代码层面该如何实现,需要注意,责任链模式的定义分为两个部分
- 处理器,通常定义接口,与提供接口实现
- 处理器链,可以理解为处理器容器
2.1.1.处理器接口
/**
* 责任链模式,处理器接口
*
* @author ThinkPad
* @version 1.0
* @date 2021/5/5 20:10
*/
public interface Handler {
/**
* 处理器接口方法
* @return
*/
boolean handle();
}
2.1.2.处理器A
/**
* 处理器A
*
* @author ThinkPad
* @version 1.0
* @date 2021/5/5 20:12
*/
public class HandlerA implements Handler{
/**
* 处理器接口方法
*
* @return
*/
@Override
public boolean handle() {
System.out.println("2.HandlerA...处理执行.");
return true;
}
}
2.1.3.处理器B
/**
* 处理器B
*
* @author ThinkPad
* @version 1.0
* @date 2021/5/5 20:12
*/
public class HandlerB implements Handler{
/**
* 处理器接口方法
*
* @return
*/
@Override
public boolean handle() {
System.out.println("3.HandlerB...处理执行.");
return true;
}
}
2.1.4.处理器链
/**
* 责任链模式,处理器链
*
* @author ThinkPad
* @version 1.0
* @date 2021/5/5 20:13
*/
public class HandlerChain {
/**
* 处理器容器
*/
private List<Handler> handlerList = new ArrayList<>();
/**
* 添加处理器
* @param handler
*/
public void addHandler(Handler handler){
handlerList.add(handler);
}
/**
* 处理器链传递执行
* @return
*/
public void handle(){
for(Handler handler : handlerList){
handler.handle();
}
}
}
2.1.5.使用案例
public static void main(String[] args) {
// 1.创建处理器链
HandlerChain handlerChain = new HandlerChain();
// 2.添加处理器
handlerChain.addHandler(new HandlerA());
handlerChain.addHandler(new HandlerB());
// 3.处理执行
System.out.println("1.发送者,发送业务请求.");
handlerChain.handle();
System.out.println("4.接收者,完成业务请求处理.");
}
#执行结果
1.发送者,发送业务请求.
2.HandlerA...处理执行.
3.HandlerB...处理执行.
4.接收者,完成业务请求处理.
2.2.过滤器filter源码分析
filter是servlet规范中很重要的一个组件,现在我们知道了它的实现机制就是责任链模式。那么我们说关注责任链模式,主要关注两个内容
- 处理器,在过滤器中,Filter即是处理器接口
- 处理器链,在过滤器中,FilterChain即是处理器链接口
接下来我把关键源码贴出来,并附上相关的注释,相信你理解起来不会有太大的难度
2.2.1.Filter接口
public interface Filter {
......省略其它代码......
/*
*关键方法:我们扩展实现Filter,主要就是重写该方法
*处理业务逻辑后,再通过FilterChain.doFilter方法,继续执行后续的过滤器
***/
void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException;
......省略其它代码......
}
2.2.2.FilterChain接口
public interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;
}
2.2.3.FilterChain接口实现
public final class ApplicationFilterChain implements FilterChain {
// 处理器容器
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
// 当前执行哪一个处理器计数
private int pos = 0;
// 总处理器数
private int n = 0;
/*
*处理器链执行入口方法
*/
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
......省略其它代码......
// 调用内部处理方法
this.internalDoFilter(request, response);
......省略其它代码......
}
/*
*处理器链内部处理方法
*/
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// 还没有执行到最后一个过滤器,继续处理执行
if (this.pos < this.n) {
// 获取到当前过滤器
ApplicationFilterConfig filterConfig = this.filters[this.pos++];
Filter filter = filterConfig.getFilter();
// 过滤器业务处理执行
filter.doFilter(request, response, this);
......省略其它代码......
}
}
}
2.3.拦截器interceptor源码分析
分析完过滤器Filter、FilterChain源码,不难看出过滤器是标准的责任链模式实现,源码都比较简单。
接下来我们继续分析springmvc提供的拦截器interceptor的源码,同样我把关键源码贴出来,附上注释方便你理解。
2.3.1.HandlerInterceptor处理器接口
springmvc提供的拦截器,将处理器方法分为前置方法(preHandle),与后置方法(postHandle),分别对应了请求的去,来
public interface HandlerInterceptor {
// 1.controller方法执行前执行
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
// 2.controller方法正常执行后执行
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// 3.只要进入该拦截器,即可执行
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
2.3.2.HandlerExecutionChain处理器链
public class HandlerExecutionChain {
// 处理器容器
@Nullable
private HandlerInterceptor[] interceptors;
@Nullable
private List<HandlerInterceptor> interceptorList;
/*
*添加处理器
*/
public void addInterceptor(HandlerInterceptor interceptor) {
this.initInterceptorList().add(interceptor);
}
/*
*controller方法执行前执行,前置方法
*/
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)) { // 触发执行afterCompletion
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
}
return true;
}
/*
*controller方法执行正常执行后执行,后置方法
*/
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable 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);
}
}
}
}
2.4.理解filter、interceptor、aop并存
理解了如何自定义实现责任链设计模式,以及分析了Filter、Interceptor的源码后,相信你对责任链模式,已经有一个比较好的掌握了,应该已经get到它的点了。
最后我们再来看一个问题,过滤器Filter、拦截器Interceptor、aop,它们处理的业务场景都非常相似,如果你的项目中,它们同时存在的话,执行顺序是什么样的呢?我们看一个图,你应该可以有答案了