zoukankan      html  css  js  c++  java
  • 【设计模式】基于spring特性的责任链模式

    【设计模式】基于spring特性的责任链模式

    业务场景:

    业务场景:开发中,需要对返回进行一系列的策略过滤,直接在一个方法中进行,代码比较长,耦合也是比较深。所以用责任链的模式进行解耦,同时可以动态配置责任链,实现动态拔插。

    设计:

    定义一个过滤链接口:

    public interface IFilterChain<ReqT,repD> {
        void doFilter(ReqT req, repD rep);
    }
    
    

    实现接口:这就是一个过滤链的对象

    public class LinkedFilterChain implements IFilterChain<RequestContext, RespondContext> ,Cloneable {
    
        List<IWorkFilter<RequestContext,RespondContext>> filterChain;
    
        @Override
        public void doFilter(RequestContext req, RespondContext rep) {
            // 循环执行责任链
            for (IWorkFilter<RequestContext, RespondContext> filterChain : filterChain) {
                 filterChain.doFilter(req,rep);
            }
        }
    
    
        public List<IWorkFilter<RequestContext, RespondContext>> getFilterChains() {
            return filterChain;
        }
    
        public void setFilterChains(List<IWorkFilter<RequestContext, RespondContext>> filterChains) {
            this.filterChain = filterChains;
        }
    
        @Override
        protected LinkedFilterChain clone() throws CloneNotSupportedException {
            return (LinkedFilterChain) super.clone();
        }
    }
    

    通过doFilter方法执行过滤,这只是一个简单的过滤链,你也可以按照业务需求实现更多的功能,比如:快速失败,等等。。

    如何使用

    1:定义一个过滤接口:

    public interface IWorkFilter<ReqT,RepD> extends Cloneable {
        void doFilter(ReqT req, RepD rep);
    }
    

    实现类为过滤节点,这里demo就建立两个过滤节点,通过@Order 实现注入链的顺序

    @Component
    @Order(1)
    @Slf4j
    public class FirstLevelWorkFilter implements IWorkFilter<RequestContext,RespondContext> {
        @Override
        public void doFilter(RequestContext req, RespondContext rep) {
            log.info("一级处理器执行。。。");
        }
    }
    
    @Component
    @Order(2) // 可以通过order对注入责任链的顺序控制
    @Slf4j
    public class SecondLevelWorkFilter implements IWorkFilter<RequestContext,RespondContext> {
        @Override
        public void doFilter(RequestContext req, RespondContext rep) {
            log.info("执行二级过滤器。。。。");
        }
    
    }
    

    2:建立一个过滤链工厂

    • 可以通过incloudChain 在配置文件中动态注入需要执行的过滤链
    • 通过spring的特性注入所有的过滤链,按照过滤链类名和实现类存入map
    • 提供获取实例的方法,返回过滤链对象
    @Component
    @Data
    @Slf4j
    public class FilterFactory {
      private List<IWorkFilter<RequestContext, RespondContext>> filterList;
      private Map<String, IWorkFilter<RequestContext, RespondContext>> filterMap = new HashMap<>();
      private LinkedFilterChain linkedFilterChain;
    
      //@Value("#{chain}")
      List<String> incloudChain = new ArrayList<>(); // 配置执行链
    
      // 可以有两种方法注入 1: @Autowired  2:构造器注入
      @Autowired(required = false)
      private List<IWorkFilter<RequestContext, RespondContext>> filters;
    
      public FilterFactory(List<IWorkFilter<RequestContext, RespondContext>> filters) {
            filterList = filters;
        }
    
      @PostConstruct
      public void init() {
        // 原始链集合 ,可以基于动态配置,对执行的链接灵活拔插
        for (IWorkFilter filter : filterList) {
          filterMap.put(filter.getClass().getSimpleName(), filter);
        }
        // 获取执行链
        updateChain();
      }
    
      private void updateChain() {
        LinkedFilterChain realChain = new LinkedFilterChain();
        List<IWorkFilter<RequestContext, RespondContext>> filters = new ArrayList<>();
        realChain.setFilterChains(filters);
        this.linkedFilterChain = realChain;
        if (CollectionUtils.isEmpty(incloudChain)) {
            filters.addAll(filterList);
        }
        for (String filterName : incloudChain) {
          IWorkFilter realFilter = filterMap.get(filterName);
          filters.add(realFilter);
        }
    
      }
    
      public LinkedFilterChain getInstance() {
          LinkedFilterChain filterChain = null;
          try{
              filterChain = linkedFilterChain.clone();
          }catch (Exception e){
            log.error("get linkedFilterChain instance got error" ,e);
          }
          return filterChain;
      }
    }
    

    测试

    测试类

    @Autowired
      FilterFactory filterFactory;
    
     @Test
      void testFilteChain(){
        LinkedFilterChain instance = filterFactory.getInstance();
        RequestContext requestContext = new RequestContext();
        RespondContext respondContext = new RespondContext();
        instance.doFilter(requestContext,respondContext);
      }
    
    2021-03-14 16:43:06.679  INFO 22120 --- [           main] c.l.d.p.d.c.filter.FirstLevelWorkFilter  : 一级处理器执行。。。
    2021-03-14 16:43:06.680  INFO 22120 --- [           main] c.l.d.p.d.c.f.SecondLevelWorkFilter      : 执行二级过滤器。。。。
    

    总结:

    ​ 责任链模式非常适合逻辑比较多的业务,按照每个业务特点拆分成一个个的节点,可以让代码更优雅。这是一个简单demo,实际在使用的时候,可以按照业务需求优化。

    That is all~~

  • 相关阅读:
    echart------属性详细介绍
    网页链接(插件,判断服务)
    简单的轮播效果
    实时时间
    Oracle Partition By 的使用
    Java配置----JDK开发环境搭建及环境变量配置
    流程控制语句以及引号的使用
    解决报表表头格式问题
    k3could报表中替换最后行汇总字段方法
    k3cloud中使用委托添加提示对话框点击确定后执行方法
  • 原文地址:https://www.cnblogs.com/simple-flw/p/14533091.html
Copyright © 2011-2022 走看看