这里我们介绍日志记录与MDC。
两者息息相关,当我们记录日志的时候,需要记录一些上下文信息。比如线程号与当前线程级别、当前时间。但是如果我们需要记录一些当前登录的用户与正在操作的订单,则是存在MDC中。可以把它理解为一些上下文的数据存储在线程变量里。当我们需要判断问题时作为诊断信息输出。但是有一些步骤需要注意,如下:
接下来我们来测试一下日志记录。
1、创建ConfigMDCTest测试类
2、赋值MyUnitTest中的内容
这里我们测试就直接使用自带的MyUnitTest的类内容就可以。复制好后,我们新建的ConfigMDCTest内容如下:
package com.jjf.activiti.config;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* MDC测试
*/
public class ConfigMDCTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMDCTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
@Deployment(resources = {"com/jjf/activiti/my-process.bpmn20.xml"}) //单元测试启动之前将这个定义文件部署到流程引擎中
public void test() {
ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
assertNotNull(processInstance);
Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
assertEquals("Activiti is awesome!", task.getName());
}
}
然后我们测试执行结果:
加载了默认的 activiti.cfg.xml 脚本,并执行h2的三个运行脚本。
3、看看my-process.bpmn20.xml文件
这个是系统自己创建流程文件。可以看到就三个结点,很简洁,所以很适合我们来测试使用。
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="my-process"> <!-- 流程文件名my-process -->
<startEvent id="start" /> <!-- 开始结点 -->
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" /> <!-- 将开始结点与someTask作业连接 -->
<userTask id="someTask" name="Activiti is awesome!" /> <!-- 一个Task作业 -->
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" /> <!-- 结束结点 -->
</process>
</definitions>
4、在test函数中打开LogMDC
LogMDC.setMDCEnabled(true); //打开LogMDC
但是我们知道MDC只有执行过程中出现异常才会被记录下来,所以我们这里还需要创建MDC拦截器。
5、创建MDCCommandInvoker拦截器
在main目录中创建一个interceptor目录,在其中创建MDCCommandInvoker
这里我们先看DebugCommandInvoker这个类,我们的拦截器需要继承他。
将选中的部分赋值拷贝到MDCCommandInvoker中:
package com.jjf.activiti.interceptor;
import org.activiti.engine.debug.ExecutionTreeUtil;
import org.activiti.engine.impl.agenda.AbstractOperation;
import org.activiti.engine.impl.interceptor.DebugCommandInvoker;
import org.activiti.engine.logging.LogMDC;
public class MDCCommandInvoker extends DebugCommandInvoker {
@Override
public void executeOperation(Runnable runnable) { //继承了DebugCommandInvoker父类的内容
boolean mdcEnable = LogMDC.isMDCEnabled(); //判断MDC是否生效
LogMDC.setMDCEnabled(true); //不管MDC是否生效,都将MDC设置为true
if (runnable instanceof AbstractOperation) { //判断可运行对象(runnable)是不是流程引擎支持的Operation
AbstractOperation operation = (AbstractOperation)runnable; //将runnable强制转换为AbstractOperation
if (operation.getExecution() != null) { //如果operation出现异常则执行
LogMDC.putMDCExecution(operation.getExecution());
}
}
super.executeOperation(runnable);
LogMDC.clear(); //最后将它清理
if( !mdcEnable ){ //mdcEnable不生效
LogMDC.setMDCEnabled(false); //把状态再设置为不生效
}
}
}
6、配置文件中配置我们定义的拦截器
首先我们尽量不要修改默认的配置文件,所以重新创建一个新的xml文件:
在activiti_mdc.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">
<property name="jdbcUrl" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000;MVCC=TRUE" />
<property name="jdbcDriver" value="org.h2.Driver" />
<property name="jdbcUsername" value="sa" />
<property name="jdbcPassword" value="" />
<property name="commandInvoker" ref="commandInvoker"/>
</bean> <!-- 默认数据库的配置 h2数据库 -->
<bean id="commandInvoker" class="com.jjf.activiti.interceptor.MDCCommandInvoker"/>
</beans>
7、修改ConfigMDCTest测试类的配置文件路径
在@Rule中修改为我们定义的 activiti_mdc.cfg.xml 文件
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_mdc.cfg.xml");
8、输出测试结果
我们可以看到效果,执行过程中都可以看到流程编译的ID等内容。