HistoryService
HistoryService历史服务
1.功能:
-
管理流程结束后的历史数据
-
构建历史数据的查询对象
-
根据流程实例ID删除流程历史数据
2.HistoryService历史数据实体
HistoryProcessInstance -> 历史流程实例实体类
HistoricVariableInstance -> 流程或任务变量值的实体
HistoricActivityInstance -> 单个活动结点执行的信息
HistoricTaskInstance -> 用户任务实例的信息
HistoricDetail -> 历史流程活动任务详细信息(Form属性信息)
-->HistoryService构建历史查询对象
-
create[历史数据实体]Query
-
createNative[历史数据实体]Query
-
createProcessInstanceHistoryLogQuery(查出一个流程实例的一个对象,每次只能查出一条记录)
-->HistoryService删除历史操作
-
deleteHistoricProcessInstance
-
deleteHistoricTaskInstance
具体运用
package com.syc.activiti.coreapi;
import com.google.common.collect.Maps;
import org.activiti.engine.HistoryService;
import org.activiti.engine.history.*;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceBuilder;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.ActivitiRule;
import org.activiti.engine.test.Deployment;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.junit.Rule;
import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
public class HistoryServiceTest {
private static final Logger LOGGER = LoggerFactory.getLogger(HistoryServiceTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_history.cfg.xml");
@Test
@Deployment(resources = "my-process.bpmn20.xml")
public void testHistory(){
HistoryService historyService = activitiRule.getHistoryService();
ProcessInstanceBuilder processInstanceBuilder = activitiRule.getRuntimeService().createProcessInstanceBuilder();
Map<String, Object> variables = Maps.newHashMap();
variables.put("key0", "value0");
variables.put("key1", "value1");
variables.put("key2", "value2");
Map<String, Object> transientVariables = Maps.newHashMap();
transientVariables.put("tkey1", "tvalue1");
ProcessInstance processInstance = processInstanceBuilder.processDefinitionKey("my-process").variables(variables).transientVariables(transientVariables).start();//启动流程的定义Key
//修改变量
activitiRule.getRuntimeService().setVariable(processInstance.getId(),"key1", "value1_1");
Task task = activitiRule.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
// activitiRule.getTaskService().complete(task.getId(),variables);
Map<String, String> properties = Maps.newHashMap();
properties.put("fkey1", "fvalue1");
properties.put("key2", "value_2_2");
activitiRule.getFormService().submitTaskFormData(task.getId(), properties);
List<HistoricProcessInstance> historicProcessInstances = historyService.createHistoricProcessInstanceQuery().listPage(0,100);
for(HistoricProcessInstance historicProcessInstance : historicProcessInstances){
LOGGER.info("historicProcessInstance = {}", ToStringBuilder.reflectionToString(historicProcessInstance, ToStringStyle.JSON_STYLE));
}
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().listPage(0, 100);
for(HistoricActivityInstance historicActivityInstance : historicActivityInstances){
LOGGER.info("historicActivityInstance = {}", historicActivityInstance);
}
List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery().listPage(0, 100);
for(HistoricTaskInstance historicTaskInstance : historicTaskInstances){
LOGGER.info("historicTaskInstance = {}", ToStringBuilder.reflectionToString(historicTaskInstance,ToStringStyle.JSON_STYLE));
}
List<HistoricVariableInstance> historicVariableInstances = historyService.createHistoricVariableInstanceQuery().listPage(0, 100);
for(HistoricVariableInstance historicVariableInstance : historicVariableInstances){
LOGGER.info("historicVariableInstance = {}", historicVariableInstance);
}
List<HistoricDetail> historicDetails = historyService.createHistoricDetailQuery().listPage(0, 100);
for(HistoricDetail historicDetail : historicDetails){
LOGGER.info("historicDetail = {}", historicDetail);
}
ProcessInstanceHistoryLog processInstanceHistoryLog = historyService.createProcessInstanceHistoryLogQuery(processInstance.getId()).includeVariables().includeFormProperties().includeComments().includeTasks().includeActivities().includeVariables().singleResult();
List<HistoricData> historicDataList = processInstanceHistoryLog.getHistoricData();
for(HistoricData historicData : historicDataList){
LOGGER.info("historicData = {}", historicData);
}
historyService.deleteHistoricProcessInstance(processInstance.getId());
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
LOGGER.info("historicProcessInstance = {}", historicProcessInstance);
}
}
ManagementService
1、Activiti核心API中的其他管理服务
-
管理服务ManagementService
-
动态流程定义服务DynamicBpmnService(实际业务开发中很少用到)
管理服务ManagementService
-
Job任务管理
-
数据库相关通用操作
-
执行流程引擎命令(Command)
---> Job任务查询
工作查询对象
---> 数据库相关操作
-
查询表结构元数据(TableMetaData)
-
通用表查询(TablePageQuery)
-
执行自定义的Sql查询(executeCustomSql)
需要先在my-process-job.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">
<startEvent id="start">
<timerEventDefinition> <!-- 配置定时器 -->
<timeCycle>R5/PT10S</timeCycle> <!--循环执行5次,每10秒执行一次-->
</timerEventDefinition>
</startEvent>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<userTask id="someTask" name="Activiti is awesome!" />
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
</definitions>
在activiti_job.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:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf-8&useSSL=false"/>
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="123456"/>
<property name="asyncExecutorActivate" value="true"/><!-- 配置启动异步任务 -->
<property name="databaseSchemaUpdate" value="true"/><!-- create-drop指明数据库必须是空的 -->
<property name="customMybatisMappers">
<set>
<value>com.imooc.activiti.mapper.MyCustomMapper</value>
</set>
</property>
</bean>
</beans>
ManagementService核心代码
package com.syc.activiti.coreapi;
import com.imooc.activiti.mapper.MyCustomMapper;
import org.activiti.engine.ManagementService;
import org.activiti.engine.impl.cmd.AbstractCustomSqlExecution;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.management.TablePage;
import org.activiti.engine.runtime.DeadLetterJobQuery;
import org.activiti.engine.runtime.Job;
import org.activiti.engine.runtime.JobQuery;
import org.activiti.engine.runtime.SuspendedJobQuery;
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 sun.misc.Resource;
import java.util.List;
import java.util.Map;
public class ManagementServiceTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ManagementServiceTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule("activiti_job.cfg.xml");
/**
* Job任务管理测试
*/
@Test
@Deployment(resources = {"my-process-job.bpmn20.xml"})
public void testJobQuery(){
ManagementService managementService = activitiRule.getManagementService();
List<Job> TimerJobList = managementService.createTimerJobQuery().listPage(0, 100);
for(Job timerJob : TimerJobList){
LOGGER.info("timerJob = {}", timerJob);
}
//获取其他三种工作查询对象
JobQuery jobQuery = managementService.createJobQuery();
SuspendedJobQuery suspendedJobQuery = managementService.createSuspendedJobQuery();
DeadLetterJobQuery deadLetterJobQuery = managementService.createDeadLetterJobQuery();
}
/**
* 数据库相关的工作管理测试
*/
@Test
@Deployment(resources = {"my-process-job.bpmn20.xml"})
public void testTablePageQuery(){
ManagementService managementService = activitiRule.getManagementService();
TablePage tablePage = managementService.createTablePageQuery().tableName(managementService.getTableName(ProcessDefinitionEntity.class)).listPage(0, 100);
List<Map<String, Object>> rows = tablePage.getRows();
for(Map<String, Object> row : rows){
LOGGER.info("row = {}", row);
}
}
/**
* 自定义的SQL查询操作
*/
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testCustomerSql(){
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
ManagementService managementService = activitiRule.getManagementService();
List<Map<String, Object>> mapList = managementService.executeCustomSql(
new AbstractCustomSqlExecution<MyCustomMapper, List<Map<String, Object>>>( //自定义的抽象执行器,MyCustomMapper为自定义的接口
MyCustomMapper.class) {
@Override
public List<Map<String, Object>> execute(MyCustomMapper o) {
return o.findAll();
}
});
for(Map<String, Object> map : mapList){
LOGGER.info("map = {}", map);
}
}
//流程定义实体
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testCommand(){
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
ManagementService managementService = activitiRule.getManagementService();
ProcessDefinitionEntity processDefinitionEntity = managementService.executeCommand(new Command<ProcessDefinitionEntity>() {
@Override
public ProcessDefinitionEntity execute(CommandContext commandContext) {
ProcessDefinitionEntity processDefinitionEntity = commandContext
.getProcessDefinitionEntityManager().findLatestProcessDefinitionByKey("my-process");
return processDefinitionEntity;
}
});
LOGGER.info(" processDefinitionEntity = {}", processDefinitionEntity);
}
}
异常策略
ActivitiException异常与描述(所有的异常都是ActivitiException的子类,而ActivitiException又继承自Java 中的 RuntimeException)
异常1:流程启动的时候发生;
异常2:并发量较高时发生;
异常3:类异常,损失较大;
异常4:操作对象的时候,这个对象已经被别人执行了;
异常5:参数问题比较常见;
异常6:异常抛出的方式,提醒客户这次调用时失败的;
异常7:流程定义文件可以配置对这个异常的监听,可以做一些特定的跳转