• 命令模式与责任链模式以及命令拦截器的配置(学习笔记)


    阿西吧,写了一个多小时的博客不小心点到了360清理资源 ,直接给我关了。服了,直接放图了

    命令模式:

      command : 抽象的 命令接口

     concretecommand:基于命名 接口的命令实现,定义命令具体做什么的

    构造命令需要传入一个参数 也就是接收者

     receiver:接收者,接收命令

    在接收了以后,再根据接收者与命令实现创建出命令来

    这个命令由invoker来执行它

    其实命令执行器是间接的去调用命令实现concretecommand的execute()方法,最终再去调用receiver中的action()方法

    client其实不属于命令模式,它只是作为客户调用命令模式的切入点。

    命令模式时序图↓:


    责任链模式:

    哪怕不做任何配置,activiti也会产生一个默认的commandinterceptor的拦截器链(责任链)

    在它之前我们可以配置customPreCommandInterceptors在它之后我们可以配置customPostCommandInterceptors或者我们的自定义拦截器,在这些都执行完了以后,最后会有一个command invoker 执行。

    为什么会这样呢,因为它就是我们最终的命令执行者。从图中可以看出来,在我们执行customPre中的execute实现时,execute实现大多是调用了next的实现,一次类推,只有最后的command invoker执行时是调用了执行器,它就不再去考虑next下一个对象是什么了。

    一环扣一环。


     命令拦截器配置:

     activiti6都有以下拦截器:

    下面贴上测试代码:

    自定义时长拦截器DurationCommandInterceptor:

    public class DurationCommandInterceptor extends AbstractCommandInterceptor {
        private static final Logger LOGGER =  LoggerFactory.getLogger(DurationCommandInterceptor.class);
        public <T> T execute(CommandConfig config, Command<T> command){
            //记录进入拦截器时的系统时间
            long start = System.currentTimeMillis();
            try {
                //
                return this.getNext().execute(config,command);
            } finally {
                long duration = System.currentTimeMillis() - start;
                LOGGER.info("{} 执行时长 {} 毫秒",command.getClass().getSimpleName(),duration);
            }
        }
    }

     拦截器配置文件activiti_interceptor.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <bean id="processEngineConfiguration"
              class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
            <!-- 给引擎设置自定义的commandInvoker -->
            <property name="commandInvoker" ref="commandInvoker" />
            <!-- 若为true则开启记录事件、节点的状态,完成后将完成状态插入数据库,若为false则关闭,不记录 -->
            <property name="enableDatabaseEventLogging" value="true"/>
            <!-- 配置命令拦截器  这里需知道customPreCommandInterceptors与 的区别-->
            <property name="customPreCommandInterceptors">
                <list>
                    <!-- 配置上时长拦截器 -->
                    <bean class="com.yy.avtiviti.helloworld.intercept.DurationCommandInterceptor"/>
                </list>
            </property>
            <!--这个东西千万不能这样配置,否则流程无法正常运行,因为commandInterceptors是整个链的组合体<property name="commandInterceptors"/>-->
            <property name="customPostCommandInterceptors">
                <list>
                    <!-- 配置上时长拦截器 -->
                    <bean class="com.yy.avtiviti.helloworld.intercept.DurationCommandInterceptor"/>
                </list>
            </property>
        </bean>
        <bean id="commandInvoker" class="com.yy.avtiviti.helloworld.intercept.MDCCommandInvoker"/>
    
    </beans>

    最后贴上测试类configInterceptorTest:

    public class configInterceptorTest {
        private static final Logger LOGGER =  LoggerFactory.getLogger(configTest.class);
    
        @Rule
        public ActivitiRule activitiRule = new ActivitiRule("activiti_interceptor.cfg.xml");//传入自定义的mdc配置文件
    
        @Test
        @Deployment(resources = {"my-process.bpmn20.xml"})//流程定义文件
        public void test() {
            ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
            Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
            activitiRule.getTaskService().complete(task.getId());
        }
    
    
    }

    测试结果如下:

  • 相关阅读:
    winsows10 小技巧
    数组与智能指针
    卸载 VS2015
    Effective C++
    修改 git commit 的信息
    线程管理
    并发编程简介
    个别算法详解
    git 删除某个中间提交版本
    git 查看某一行代码的修改历史
  • 原文地址:https://www.cnblogs.com/xk920/p/10680770.html
Copyright © 2020-2023  润新知