美文网首页
04.设计模式之责任链模式

04.设计模式之责任链模式

作者: 滔滔逐浪 | 来源:发表于2022-06-21 22:40 被阅读0次

    什么是责任链模式

    链表数据机构:
    客户端发出一个请求,链上的对象都有机会来处理这一个请求,而客户端不需要知道谁是具体的处理对象。这样就实现了请求者和接受者之间的解耦,并且在客户端可以实现实现动态的组合职责链。使编程更有灵活性。
    定义: 使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。实际就是一个递归调用。

    要点主要是:

    1,有多个对象共同对一个任务进行处理
    2,这些对象使用链式存储结构,形成一个链,每个一个对象知道自己的下一个对象。
    3,一个对象对任务进行处理,可以增加一些操作后将对象传递个下一个任务。也可以在此对象上结束任务的处理,并结束任务。
    4,客户端负责组装链式结构,但是客户端不需要关心最终不需要关心最终是谁来处理了任务。


    image.png

    责任链模式的优缺点:

    优点:
    责任链模式的最主要功能是:动态组合,请求者和接受者解耦。
    请求者和接受者松散耦合:请求者不需要知道接受者,也不需要知道如何处理,每个职责只负责自己的职责范围,其他的交给后继者。各个组件间完全解耦。
    动态组合职责:职责链模式会把功能分散到单独的职责对象中,然后再使用时动态的组合形成链。从而可以灵活的分配职责对象,也可以灵活的添加改变对象职责。
    缺点:
    产生很多细粒度的对象,因为功能处理都分散到了单独的职责对象中,每个对象功能单一,要把整个流程处理完,需要很多职责对象。会产生大量的细粒度职责对象。
    不一定能处理: 每个职责对象都只负责自己部分,这样就可以出现某个请求,即使把整个链走完都没有职责对象处理它,这样就需要提供默认处理,并且注意构造链的有效性。
    责任链模式应用场景
    1,多条件流程判断权限控制
    2,erp系统 流程审批
    3,java 过滤器的底层实现filter
    4,工作流
    比如:在java过滤器中客户端发送请求到客户端,过滤会经过参数过滤,sesson过滤,表单过滤,隐藏过滤,检测请求头过滤。

    责任链模式应用场景:

    网关权限控制责任链模式:
    在网关作为微服务程序的入口,拦截客户端所有的请求实现权限控制
    比如先判断Api接口限流,黑名单,用户会话,参数过滤。
    Api接口限流-黑名单拦截--用户会话--参数过滤

    责任链整合工厂模式:

    GatewayHandler抽象角色;

    package com.taotao.chain;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:18
     */
    public abstract class  GatewayHandler {
        /**
         * 处理流程
         */
        public abstract void doServices();
        /**
         * 下一个nextGatewayHandler
         */
        public GatewayHandler nextGatewayHandler;
    
        /**
         * 获取当前handler的下一个
         */
       // public  abstract  void setNextGatewayHandler(GatewayHandler nextGatewayHandler);
        public void setNextGatewayHandler(GatewayHandler nextGatewayHandler) {
            this.nextGatewayHandler=nextGatewayHandler;
        }
    }
    
    
    

    具体Handler实现

    package com.taotao.chain.impl;
    
    import com.taotao.chain.GatewayHandler;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:24
     */
    @Slf4j
    public class CurrentLimitHandler extends GatewayHandler {
        @Override
        public void doServices() {
          log.info("<第一关api接口限流>");
          //第一关放行 过了
            nextGatewayHandler.doServices();
        }
    
    
    
    
    }
    
    
    
    package com.taotao.chain.impl;
    
    import com.taotao.chain.GatewayHandler;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:24
     */
    @Slf4j
    public class BlackLimitHandler extends GatewayHandler {
        @Override
        public void doServices() {
          log.info("<<第二关 判断是否ip黑名单>");
            nextGatewayHandler.doServices();
        }
    
    
    
    }
    
    
    package com.taotao.chain.impl;
    
    import com.taotao.chain.GatewayHandler;
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:24
     */
    @Slf4j
    public class ConversationLimitHandler extends GatewayHandler {
        @Override
        public void doServices() {
          log.info("<<第三关 判断用户是否验证token信息>");
    
        }
    
    
    
    
    
    }
    
    
    

    FactoryHandler

    package com.taotao.chain.factory;
    
    import com.taotao.chain.GatewayHandler;
    import com.taotao.chain.impl.BlackLimitHandler;
    import com.taotao.chain.impl.ConversationLimitHandler;
    import com.taotao.chain.impl.CurrentLimitHandler;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:32
     */
    public class FactoryHandler {
        public static GatewayHandler getGatewayHandler() {
    
    
            CurrentLimitHandler currentLimitHandler=new CurrentLimitHandler();
            //1 设置黑名单BlackListHandler
            BlackLimitHandler blackLimitHandler=new BlackLimitHandler();
           blackLimitHandler.setNextGatewayHandler(new ConversationLimitHandler());
            //2 设置api接口限流的handler下一个handler黑名单Handler
            currentLimitHandler.setNextGatewayHandler(blackLimitHandler);
            return currentLimitHandler;
        }
    
        public static void main(String[] args) {
             GatewayHandler gatewayHandler=FactoryHandler.getGatewayHandler();
             gatewayHandler.doServices();
        }
    }
    
    
    

    责任链整合spring模式
    IOC抽象工厂

    package com.taotao.chain.factory;
    
    import com.taotao.chain.GatewayHandler;
    import com.taotao.chain.impl.BlackLimitHandler;
    import com.taotao.chain.impl.ConversationLimitHandler;
    import com.taotao.chain.impl.CurrentLimitHandler;
    import com.taotao.utils.SpringUtils;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-25  23:32
     */
    public class FactoryHandler {
        public static GatewayHandler getGatewayHandler() throws Exception {
           /* CurrentLimitHandler currentLimitHandler=new CurrentLimitHandler();
            //1 设置黑名单BlackListHandler
            BlackLimitHandler blackLimitHandler=new BlackLimitHandler();
           blackLimitHandler.setNextGatewayHandler(new ConversationLimitHandler());
            //2 设置api接口限流的handler下一个handler黑名单Handler
            currentLimitHandler.setNextGatewayHandler(blackLimitHandler);*/
            ConversationLimitHandler conversationLimitHandler = SpringUtils.getBean("conversationLimitHandler", ConversationLimitHandler.class);
            BlackLimitHandler blackLimitHandler = SpringUtils.getBean("blackLimitHandler", BlackLimitHandler.class);
            blackLimitHandler.setNextGatewayHandler(conversationLimitHandler);
            // 2.设置api接口限流的Handler 下一个Handler 黑名单Handler
            CurrentLimitHandler currentLimitHandler = SpringUtils.getBean("currentLimitHandler", CurrentLimitHandler.class);
            currentLimitHandler.setNextGatewayHandler(blackLimitHandler);
            return currentLimitHandler;
        }
    
        public static void main(String[] args) throws Exception {
             GatewayHandler gatewayHandler=FactoryHandler.getGatewayHandler();
             gatewayHandler.doServices();
        }
    }
    
    
    

    具体Handler实现

    package com.taotao.mapper;
    
    import com.taotao.entity.GatewayHandlerEntity;
    import org.apache.ibatis.annotations.Select;
    
    public interface GatewayHandlerMapper {
    
        /**
         * 获取第一个GatewayHandler
         *
         * @return
         */
        @Select("SELECT  handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid  FROM gateway_handler WHERE  prev_handler_id is null;;")
        GatewayHandlerEntity getFirstGatewayHandler();
    
        @Select("SELECT  handler_name AS handlerName,handler_id AS handlerid ,prev_handler_id AS prevhandlerid ,next_handler_id AS nexthandlerid   FROM gateway_handler WHERE  handler_id=#{handlerId}")
        GatewayHandlerEntity getByHandler(String handlerId);
    
    }
    
    
    package com.taotao.service;
    
    import com.mysql.cj.log.Log;
    import com.taotao.chain.GatewayHandler;
    import com.taotao.chain.factory.FactoryHandler;
    import com.taotao.manage.GatewayHandlerManage;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-26  10:11
     */
    @RestController
    @Slf4j
    public class TestChainService {
        @Autowired
        private GatewayHandlerManage gatewayHandlerManage;
    
        /*
         *测试责任链
         */
        @RequestMapping("/testChain")
        public String testChain() {
            try {
              /*  GatewayHandler gatewayHandler = FactoryHandler.getGatewayHandler();
                gatewayHandler.doServices();*/
    
                GatewayHandler gatewayHandler = gatewayHandlerManage.getFirstGatewayHandler();
                gatewayHandler.doServices();
    
            } catch (Exception e) {
                log.error("<权限不足,中间部分环节没有通过>");
                return "fail";
            }
    
            //业务代码 更新doService方法中某一个环节 ,没有过的情况就不会执行
            /**
             * 封装的方法
             * 1,方法上加上返回值 拦截器(多拦截器)true
             * 2,抛出异常
             */
            return "业务代码";
        }
    
    }
    
    
    package com.taotao.utils;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    /**
     * @author wangjin
     * @title: SpringUtils
     * @projectName mayikt_ strategy
     * @description: TODO
     * @date 2022/6/12 0012 22:26
     */
    @Component
    @Slf4j
    public class SpringUtils implements ApplicationContextAware {
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            SpringUtils.applicationContext = applicationContext;
        }
    
        //获取applicationContext
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    
        //通过name获取 Bean.
        public static Object getBean(String name) {
            return getApplicationContext().getBean(name);
        }
    
        //通过class获取Bean.
        public static <T> T getBean(Class<T> clazz) {
            return getApplicationContext().getBean(clazz);
        }
    
        //通过name,以及Clazz返回指定的Bean
        public static <T> T getBean(String name, Class<T> clazz) {
            try {
                return getApplicationContext().getBean(name, clazz);
            } catch (Exception e) {
                log.error("<e:{}>", e);
                return null;
            }
        }
    }
    
    
    package com.taotao.manage;
    
    import com.taotao.chain.GatewayHandler;
    import com.taotao.entity.GatewayHandlerEntity;
    import com.taotao.mapper.GatewayHandlerMapper;
    import com.taotao.utils.SpringUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.logging.log4j.util.Strings;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    /**
     * @Author: wangjin
     * @CreateTime: 2022-06-26  13:27
     */
    @Slf4j
    @Component
    public class GatewayHandlerManage {
        @Autowired
        private GatewayHandlerMapper gatewayHandlerMapper;
    
        public GatewayHandler getFirstGatewayHandler() throws Exception {
    
            GatewayHandlerEntity firstGatewayHandler = gatewayHandlerMapper.getFirstGatewayHandler();
            //先查询第一个gatewayHandler
            if (firstGatewayHandler == null) {
                //db没有配置第一个
                log.error("没有配置我们的第一个gatewayHandler");
                return null;
            }
            String firstHandlerId = firstGatewayHandler.getHandlerId();
            if (Strings.isEmpty(firstHandlerId)) {
                log.error("没有配置我们的第一个firstHandlerId");
                return null;
            }
            //2 继续 判断如果有下一个gatewayHandler直接调用gatewayHandler.setGatewayHandler();
            GatewayHandler firstHandler = SpringUtils.getBean(firstHandlerId, GatewayHandler.class);
            String nextHandlerId = firstGatewayHandler.getNextHandlerId();
            GatewayHandler tempHandlers=firstHandler;
            while (Strings.isNotBlank(nextHandlerId)) {
                GatewayHandler nextGatewayHandler = SpringUtils.getBean(nextHandlerId, GatewayHandler.class);
                tempHandlers.setNextGatewayHandler(nextGatewayHandler);
                //根据nextGatewayHandler查询数据库db信息得到下一个GatewayHandler信息
                GatewayHandlerEntity nextGatewayHandlerEntity = gatewayHandlerMapper.getByHandler(nextHandlerId);
                nextHandlerId = nextGatewayHandlerEntity.getNextHandlerId();
                tempHandlers=nextGatewayHandler;
            }
    
            return firstHandler;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:04.设计模式之责任链模式

          本文链接:https://www.haomeiwen.com/subject/mtcyvrtx.html