责任链模式(Chain Of Responsibility Pattern)
属于行为型模式
的一种,将请求沿着一条链传递,直到该链上的某个对象处理它为止。html
<!-- more -->java
定义以下:一个请求有多个对象来处理,这些对象造成一条链,根据条件肯定具体由谁来处理,若是当前对象不能处理则传递给该链中的下一个对象,直到有对象处理它为止。责任链模式
经过将请求和处理分离开来,以进行解耦。职责链模式结构的核心在于引入了一个抽象处理者。git
UML结构图web
模式结构spring
提供对后续处理者的引用
UML图以下:设计模式
1.定义AbstractHandler(抽象处理者)
,使子类造成一条链数组
public abstract class AbstractHandler { private AbstractHandler handler; public abstract void handleRequest(String condition); public AbstractHandler getHandler() { return handler; } public void setHandler(AbstractHandler handler) { this.handler = handler; } }
2.建立若干个ConcreteHandler(具体处理者)
继承AbstractHandler
,在当前处理者对象
没法处理时,将执行权传给下一个处理者对象
安全
public class ConcreteHandlerA extends AbstractHandler { @Override public void handleRequest(String condition) { if (condition.equals("A")) { System.out.println("ConcreteHandlerA处理"); } else { System.out.println("ConcreteHandlerA不处理,由其余的Handler处理"); super.getHandler().handleRequest(condition); } } } public class ConcreteHandlerB extends AbstractHandler { @Override public void handleRequest(String condition) { if (condition.equals("B")) { System.out.println("ConcreteHandlerB处理"); } else { System.out.println("ConcreteHandlerB不处理,由其余的Handler处理"); super.getHandler().handleRequest(condition); } } } public class ConcreteHandlerZ extends AbstractHandler { @Override public void handleRequest(String condition) { //通常是最后一个处理者 System.out.println("ConcreteHandlerZ处理"); } }
3.建立ChainClient(测试类)
springboot
public class ChainClient { public static void main(String[] args) { AbstractHandler handlerA = new ConcreteHandlerA(); AbstractHandler handlerB = new ConcreteHandlerB(); AbstractHandler handlerZ = new ConcreteHandlerZ(); // 如A处理不掉转交给B handlerA.setHandler(handlerB); handlerB.setHandler(handlerZ); handlerA.handleRequest("Z"); } }
4.运行效果微信
----------------------handleRequest("A")------------------------- ConcreteHandlerA处理 ----------------------handleRequest("B")------------------------- ConcreteHandlerA不处理,由其余的Handler处理 ConcreteHandlerB处理 ----------------------handleRequest("Z")------------------------- ConcreteHandlerA不处理,由其余的Handler处理 ConcreteHandlerB不处理,由其余的Handler处理 ConcreteHandlerZ处理
能够看出,客户端建立了三个处理者对象
,并指定第一个处理者对象的下家是第二个处理者对象,第二个处理者对象的下家是第三个处理者对象。而后客户端将请求传递给第一个处理者对象。
因为本示例的传递逻辑很是简单:只要有下家,就传给下家处理;若是没有下家,就自行处理。所以,第一个处理者对象接到请求后,会将请求传递给第二个处理者对象。因为第二个处理者对象没有下家,因而自行处理请求。活动时序图以下所示。
咱们常用的Filter
就使用到了责任链模式,建立一个Filter
除了要在应用中作相应配置外,还须要实现javax.servlet.Filter
接口。
@Configuration public class MyFilter implements Filter { private final static Logger LOGGER = LoggerFactory.getLogger(MyFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { LOGGER.info("init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { LOGGER.info("doFilter"); filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { LOGGER.info("destroy"); } }
使用DEBUG模式所看到的结果以下:
Filter
集
在源码ApplicationFilterChain
中,定义了一个ApplicationFilterConfig
的数组来存放全部的Filter
,使之造成链状
public final class ApplicationFilterChain implements FilterChain { // 扩容规则 public static final int INCREMENT = 10; // Filter集,默认大小为 0 个 private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; }
ApplicationFilterConfig
装载规则
在应用首次启动时,会自动实例化对象,并从web应用中读取配置的Filter的信息,而后装进该容器。
public final class ApplicationFilterConfig implements FilterConfig, Serializable { // 省略代码... }
ApplicationFilterConfig
扩容规则
//将过滤器添加到在此链条中执行的过滤器集合中。 void addFilter(ApplicationFilterConfig filterConfig) { // 防止屡次添加相同的过滤器 for(ApplicationFilterConfig filter:filters) if(filter==filterConfig) return; if (n == filters.length) { // 定义一个在原基础之上 +10 的新数组 ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT]; // 将源数组的元素拷贝到目标数组中去 System.arraycopy(filters, 0, newFilters, 0, n); // 从新赋值 filters = newFilters; } //将变量filterConfig放入ApplicationFilterConfig数组中,并将当前过滤器链里面拥有的过滤器数目+1 filters[n++] = filterConfig; }
addFilter
的使用
public static ApplicationFilterChain createFilterChain(ServletRequest request,Wrapper wrapper, Servlet servlet) { //若是没有 servlet 要执行,则返回null if (servlet == null) return null; // 建立和初始化过滤器链对象 ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; if (Globals.IS_SECURITY_ENABLED) { // 为了安全起见:不要回收 filterChain = new ApplicationFilterChain(); } else { filterChain = (ApplicationFilterChain) req.getFilterChain(); if (filterChain == null) { filterChain = new ApplicationFilterChain(); req.setFilterChain(filterChain); } } } else { // 调度程序在使用中 filterChain = new ApplicationFilterChain(); } filterChain.setServlet(servlet); filterChain.setServletSupportsAsync(wrapper.isAsyncSupported()); // 获取过滤器上下文映射 StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps(); // 若是没有过滤器映射,就认为当前执行完成 if ((filterMaps == null) || (filterMaps.length == 0)) return (filterChain); // 获取匹配的过滤器映射信息 DispatcherType dispatcher = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR); String requestPath = null; Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR); if (attribute != null){ requestPath = attribute.toString(); } String servletName = wrapper.getName(); // 将相关路径映射的过滤器添加到此过滤器链中 for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // 添加与servlet名称匹配的筛选器 for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersServlet(filterMaps[i], servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // 返回完整的过滤器链 return filterChain; }
createFilterChain
的调用
final class StandardWrapperValve extends ValveBase { public final void invoke(Request request, Response response) throws IOException, ServletException { // 省略代码... // 为这个请求建立过滤器链 ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance(); ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet); // 省略代码... filterChain.doFilter(request.getRequest(), response.getResponse()); } }
执行流程
在StandardWrapperValue类的invoke()
方法中调用ApplicationFilterChai类的createFilterChain()
方法
在ApplicationFilterChai类的createFilterChain()
方法中调用ApplicationFilterChain类的addFilter()
方法
在ApplicationFilterChain类的addFilter()
方法中给ApplicationFilterConfig数组赋值。
最后一步
在doFilter()
方法中最后会调用一个internalDoFilter()
方法,目的就是执行ApplicationFilterChain
中的所有过滤器,从代码中能够发现它调用了doFilter
,而在doFilter
又会调用internalDoFilter
从而使全部的Filter
都得以调用
private void internalDoFilter(ServletRequest request,ServletResponse response) throws IOException, ServletException { // 若是存在下一个,继续调用下一个过滤器 if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; try { Filter filter = filterConfig.getFilter(); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); } else { // 此处调用Filter的doFilter()方法 / 而 doFilter 又会调用 internalDoFilter 直到调用完全部的过滤器 filter.doFilter(request, response, this); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("filterChain.filter"), e); } return; } // 从最后一个开始调用 try { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(request); lastServicedResponse.set(response); } if (request.isAsyncSupported() && !servletSupportsAsync) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } // 包装请求 if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); } else { servlet.service(request, response); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("filterChain.servlet"), e); } finally { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }
职责链模式经过创建一条链来组织请求的处理者,请求将沿着链进行传递,请求发送者无须知道请求在什么时候、何处以及如何被处理,实现了请求发送者与处理者的解耦。在软件开发中,若是遇到有多个对象能够处理同一请求时能够应用职责链模式,例如在Web应用开发中建立一个过滤器(Filter)链来对请求数据进行过滤,在工做流系统中实现公文的分级审批等等,使用职责链模式能够较好地解决此类问题。
优势
具体请求处理者
,只须要在客户端从新建链便可,无需破坏原代码缺点
金无足赤,人无完人。就像全部的设计模式同样,有优势优缺点,可是总的来讲优势一定大于缺点或者说缺点相对于优势来讲更可控。
参考文献:http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html
全文代码:https://gitee.com/battcn/design-pattern/tree/master/Chapter11/battcn-chain-responsibility
微信公众号:battcn
(欢迎调戏)
关注公众号:battcn
,回复springboot
便可得到 <Spring Boot从入门到实战 基础实战系列教程全集>
与 <2017最新spring boot 外卖实战微信公众平台视频教程>