• Java :职责链模式


    定义:

    使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
    概述

    解决的问题

    请求和处理分开、实现解耦、提高系统的灵活性
    可以动态的调整请求的链条,增加系统灵活性

    核心要点:

    职责链模式每个执行者都包含了另一个执行者的引用。如果一个对象不能处理该请求,会把请求传递给下一个执行者。
    客户端需要动态的调整,执行者的上下级。
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    执行者-三个

    /**
     *  只处理数字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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    客户端

    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);
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    拓展

    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 {
                //资源释放 
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    拦截器的方法

    	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
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    应用场景

    1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
    2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
    3、可动态指定一组对象处理请求。
    4、比如:JS 中的事件冒泡,JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

  • 相关阅读:
    【无标题】
    BI技巧丨矩阵高亮
    【Python】 了解二分类:机器学习中的基础任务
    Json介绍,QT解析和生成Json
    C++初阶学习第三弹——类与对象(上)——初始类与对象
    Spring Boot Admin2 自定义JVM监控通知
    Arch Linux安装桌面环境
    详谈mysql各种常用操作数据表结构的用法【建议收藏】
    平曲线坐标、反算桩号计算程序
    微服务下认证授权框架的探讨
  • 原文地址:https://blog.csdn.net/promsing/article/details/126741259