Java职责链模式
小小张自由—>张有博 人气:0定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
解决的问题
请求和处理分开、实现解耦、提高系统的灵活性
可以动态的调整请求的链条,增加系统灵活性
核心要点
职责链模式每个执行者都包含了另一个执行者的引用。如果一个对象不能处理该请求,会把请求传递给下一个执行者。
客户端需要动态的调整,执行者的上下级。
Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
类图
代码实现
抽象父类
/** * 处理请求的抽象类 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/9/7 - 9:29 */ public abstract class Handler { //维持一个下一个执行者的引用 protected Handler handler; protected void setHandler(Handler handler) { this.handler = handler; } //处理请求的抽象方法 public abstract void processRequest(int request); }
执行者-三个
/** * 只处理数字1-10 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/9/7 - 9:31 */ public class ConcreteHandlerA extends Handler{ @Override public void processRequest(int request) { if (request>=0 && request<10 ){ System.out.println("ConcreteHandlerA已经处理完毕了 "+request); return; } if (handler!=null){ //下一位处理 handler.processRequest(request); } } } /** * 只处理数字10-20 * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/9/7 - 9:31 */ public class ConcreteHandlerB extends Handler{ @Override public void processRequest(int request) { if (request>=10 && request<20 ){ System.out.println("ConcreteHandlerB已经处理完毕了 "+request); return; } if (handler!=null){ //下一位处理 handler.processRequest(request); } } } /** *只处理数字30+ * * @author Promsing(张有博) * @version 1.0.0 * @since 2022/9/7 - 9:31 */ public class ConcreteHandlerC extends Handler{ @Override public void processRequest(int request) { if (request>=30 ){ System.out.println("ConcreteHandlerC已经处理完毕了 "+request); return; } if (handler!=null){ //下一位处理 handler.processRequest(request); } } }
客户端
public class Main { public static void main(String[] args) { //创建执行者 Handler h1=new ConcreteHandlerA(); Handler h2=new ConcreteHandlerB(); Handler h3=new ConcreteHandlerC(); //设置向下级的顺序,可根据配置动态设置上下级 h1.setHandler(h2); h2.setHandler(h3); int[] requests={8,11,23,50,7,19,28,40}; //循环处理请求,不同的数值,交给不同的执行者 for (int request : requests) { h1.processRequest(request); } } }
拓展
SpringMVC中DispatchServlet使用职责链
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request;//请求 HandlerExecutionChain mappedHandler = null;//执行链 try { ModelAndView mv = null; Exception dispatchException = null; try { // Determine handler for the current request. mappedHandler = getHandler(processedRequest); //根据请求-获得执行链 //判断mappedHandler是否为空,空:404 if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // 确定当前请求的处理程序适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //职责链的前置拦截 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //执行handler方法-controller mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); //职责链的后置拦截 mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } //对结果集进行处理 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { //执行完成了拦截器 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } finally { //资源释放 } }
拦截器的方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); //获得拦截器 if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) {//循环遍历执行前置拦截 HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true; } void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = 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); } } void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); //获得拦截器 if (!ObjectUtils.isEmpty(interceptors)) { for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; try { //循环遍历执行完成拦截 interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } } }
应用场景
1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
3、可动态指定一组对象处理请求。
4、比如:JS 中的事件冒泡,JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
加载全部内容