【Activiti系列学习】--17.Activiti核心API之HistoryService和ManagementService

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&amp;characterEncoding=utf-8&amp;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:流程定义文件可以配置对这个异常的监听,可以做一些特定的跳转

 

发布了66 篇原创文章 · 获赞 32 · 访问量 8528

猜你喜欢

转载自blog.csdn.net/shao_yc/article/details/105329084