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

阿西吧,写了一个多小时的博客不小心点到了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());
    }


}

测试结果如下:

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