Activiti版本:7.1.0.M3.1
Spring Boot 版本:2.1.1.RELEASE
相关依赖如下:
org.activiti
activiti-engine
7.1.0.M3.1
org.activiti
activiti-spring
7.1.0.M3.1
org.activiti
activiti-image-generator
6.0.0
相关配置如下:
package org.platform.modules.bootstrap.config;
import javax.annotation.Resource;
import org.activiti.engine.DynamicBpmnService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
@Configuration
public class ActivitiConfiguration {
@Resource(name = "routingDataSource")
private AbstractRoutingDataSource routingDataSource = null;
@Bean
public StandaloneProcessEngineConfiguration processEngineConfiguration() {
StandaloneProcessEngineConfiguration peConfiguration = new StandaloneProcessEngineConfiguration();
peConfiguration.setDataSource(routingDataSource);
peConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
peConfiguration.setAsyncExecutorActivate(false);
return peConfiguration;
}
@Bean(name = "processEngine")
public ProcessEngine processEngine() {
return processEngineConfiguration().buildProcessEngine();
}
@Bean(name = "repositoryService")
public RepositoryService repositoryService() {
return processEngine().getRepositoryService();
}
@Bean(name = "runtimeService")
public RuntimeService runtimeService() {
return processEngine().getRuntimeService();
}
@Bean(name = "taskService")
public TaskService taskService() {
return processEngine().getTaskService();
}
@Bean(name = "historyService")
public HistoryService historyService() {
return processEngine().getHistoryService();
}
@Bean(name = "managementService")
public ManagementService managementService() {
return processEngine().getManagementService();
}
@Bean(name = "dynamicBpmnService")
public DynamicBpmnService dynamicBpmnService() {
return processEngine().getDynamicBpmnService();
}
}
简单使用如下:
package org.platform.modules.process.service;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
public interface IProcessService {
/**
* 部署流程
* @param name
* @param category
* @param bpmnPath
* @param pngPath
* @throws RuntimeException
*/
public void deployProcess(String name, String category, String bpmnPath, String pngPath) throws RuntimeException;
/**
* 启动流程
* @param processDefinitionKey
* @param variables
* @param assignee
* @param nextVariables
* @return
* @throws RuntimeException
*/
public String startupProcess(String processDefinitionKey, Map variables, String assignee,
Map nextVariables) throws RuntimeException;
/**
* 处理流程
* @param processInstanceId
* @param assignee
* @param taskVariables
* @param nextVariables
* @throws RuntimeException
*/
public void handleProcess(String processInstanceId, String assignee, boolean isCandidateUser,
Map taskVariables, Map nextVariables) throws RuntimeException;
/**
* 读取任务列表
* @param assignee
* @param isCandidateUser
* @param firstResult
* @param maxResults
* @return
* @throws RuntimeException
*/
public List
package org.platform.modules.process.service.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.platform.modules.process.service.IProcessService;
import org.platform.utils.reflect.ReflectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service("processService")
public class ProcessServiceImpl implements IProcessService {
private Logger LOG = LoggerFactory.getLogger(ProcessServiceImpl.class);
@Resource(name = "repositoryService")
private RepositoryService repositoryService = null;
@Resource(name = "runtimeService")
private RuntimeService runtimeService = null;
@Resource(name = "taskService")
private TaskService taskService = null;
@Resource(name = "historyService")
private HistoryService historyService = null;
@Override
public void deployProcess(String name, String category, String bpmnPath, String pngPath) throws RuntimeException {
Deployment deployment = repositoryService.createDeploymentQuery()
.deploymentName(name).deploymentCategory(category).singleResult();
if (null != deployment) repositoryService.deleteDeployment(deployment.getId(), true);
deployment = repositoryService.createDeployment()
.addClasspathResource(bpmnPath).addClasspathResource(pngPath)
.name(name).category(category).deploy();
LOG.info("deploy process id {} name {}", deployment.getId(), deployment.getName());
}
@Override
public String startupProcess(String processDefinitionKey, Map variables, String assignee,
Map nextVariables) throws RuntimeException {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
List taskList = taskService.createTaskQuery().processInstanceId(processInstance.getId())
.orderByTaskCreateTime().desc().taskAssignee(assignee).list();
if (null == taskList || taskList.isEmpty()) return null;
Task task = taskList.get(0);
taskService.complete(task.getId(), nextVariables);
return processInstance.getId();
}
@Override
public void handleProcess(String processInstanceId, String assignee, boolean isCandidateUser,
Map taskVariables, Map nextVariables) throws RuntimeException {
TaskQuery taskQuery = taskService.createTaskQuery().processInstanceId(processInstanceId);
taskQuery = isCandidateUser ? taskQuery.taskCandidateUser(assignee) : taskQuery.taskAssignee(assignee);
String taskId = taskQuery.list().get(0).getId();
taskService.setVariables(taskId, taskVariables);
taskService.complete(taskId, nextVariables);
}
@Override
public List> readTaskList(String assignee, boolean isCandidateUser,
int firstResult, int maxResults) throws RuntimeException {
TaskQuery taskQuery = taskService.createTaskQuery().orderByTaskCreateTime().desc();
taskQuery = isCandidateUser ? taskQuery.taskCandidateUser(assignee) : taskQuery.taskAssignee(assignee);
List taskList = taskQuery.listPage(firstResult, maxResults);
List> resultList = new ArrayList>();
for (int i = 0, len = taskList.size(); i < len; i++) {
resultList.add(ReflectUtils.convertObjectToObjectMap(taskList.get(i)));
}
return resultList;
}
@Override
public List> readHistoryTaskList(String assignee, boolean isCandidateUser,
int firstResult, int maxResults) throws RuntimeException {
HistoricTaskInstanceQuery taskInstanceQuery =
historyService.createHistoricTaskInstanceQuery().orderByTaskCreateTime().desc();
taskInstanceQuery = isCandidateUser ? taskInstanceQuery.taskCandidateUser(assignee)
: taskInstanceQuery.taskAssignee(assignee);
List taskInstanceList = taskInstanceQuery.listPage(firstResult, maxResults);
List> resultList = new ArrayList>();
for (int i = 0, len = taskInstanceList.size(); i < len; i++) {
resultList.add(ReflectUtils.convertObjectToObjectMap(taskInstanceList.get(i)));
}
return resultList;
}
@Override
public List> readHistoryTaskList(String processInstanceId) throws RuntimeException {
List taskInstanceList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
List> resultList = new ArrayList>();
for (int i = 0, len = taskInstanceList.size(); i < len; i++) {
resultList.add(ReflectUtils.convertObjectToObjectMap(taskInstanceList.get(i)));
}
return resultList;
}
@Override
public void readProcessTrackingImage(String processInstanceId, OutputStream output) throws RuntimeException {
// 获取历史流程实例
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
// 获取历史流程定义
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl)
repositoryService).getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId());
// 历史活动实例
List historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();
// 已执行历史节点
List executedHistoricActivityIdList = new ArrayList();
historicActivityInstanceList.forEach(historicActivityInstance -> {
LOG.info("historic activity name {}", historicActivityInstance.getActivityName());
executedHistoricActivityIdList.add(historicActivityInstance.getActivityId());
});
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionEntity.getId());
// 已执行Flow
List executedFlowIdList = getExecutedFlowIdList(bpmnModel, historicActivityInstanceList);
ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
InputStream input = processDiagramGenerator.generateDiagram(bpmnModel, "png", executedHistoricActivityIdList,
executedFlowIdList, "宋体", "宋体", "宋体", null, 1.0d);
try {
IOUtils.copyLarge(input, output);
} catch (IOException e) {
e.printStackTrace();
}
}
private static List getExecutedFlowIdList(BpmnModel bpmnModel, List historicActivityInstanceList) {
List executedFlowIdList = new ArrayList();
for(int i = 0, len = historicActivityInstanceList.size(); i < len - 1; i++) {
HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i);
FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(historicActivityInstance.getActivityId());
List sequenceFlowList = flowNode.getOutgoingFlows();
if(sequenceFlowList.size() > 1) {
HistoricActivityInstance nextHistoricActivityInstance = historicActivityInstanceList.get(i+1);
sequenceFlowList.forEach(sequenceFlow -> {
if (sequenceFlow.getTargetFlowElement().getId().equals(nextHistoricActivityInstance.getActivityId())) {
executedFlowIdList.add(sequenceFlow.getId());
}
});
} else {
executedFlowIdList.add(sequenceFlowList.get(0).getId());
}
}
return executedFlowIdList;
}
public void readProcessInstanceState1(String processInstanceId){
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId).singleResult();
if (processInstance != null) {
LOG.info("{} 流程执行 {}", processInstance.getName(), processInstance.getActivityId());
} else {
LOG.info("流程结束");
}
}
public void readProcessInstanceState2(String processInstanceId){
HistoricActivityInstance hai = historyService.createHistoricActivityInstanceQuery()
.processInstanceId("2501").unfinished().singleResult();
if (hai!=null) {
LOG.info("{} 流程执行 {} {}", hai.getProcessInstanceId(), hai.getActivityName(), hai.getAssignee());
} else {
LOG.info("流程结束");
}
}
}
package org.platform.modules.sale.service.impl;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.platform.modules.process.service.IProcessService;
import org.platform.modules.sale.service.ISaleOrderProcessService;
import org.platform.modules.sale.service.ISaleOrderService;
import org.platform.modules.sale.service.ISaleUserService;
import org.platform.modules.user.service.IUserService;
import org.platform.utils.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service("saleOrderProcessService")
public class SaleOrderProcessServiceImpl implements ISaleOrderProcessService {
private Logger LOG = LoggerFactory.getLogger(SaleOrderProcessServiceImpl.class);
@Resource(name = "processService")
private IProcessService processService = null;
@Override
public void deploy() throws BusinessException {
processService.deployProcess("SaleOrderProcess", "sale",
"processes/SaleOrderProcess.bpmn", "processes/SaleOrderProcess.png");
}
@Override
public String startup(String saleUserAccount, String saleOrderNo, String legalAffairsUsers) throws BusinessException {
LOG.info("{} {} sale order process start!", saleUserAccount, saleOrderNo);
Map variables = new HashMap();
variables.put("saleUser", saleUserAccount);
variables.put("saleOrder", saleOrderNo);
Map nextVariables = new HashMap();
nextVariables.put("legalAffairsUsers", legalAffairsUsers);
String processInstanceId = processService.startupProcess("SaleOrderProcess", variables, saleUserAccount, nextVariables);
LOG.info("{} {} sale order process end!", saleUserAccount, saleOrderNo);
return processInstanceId;
}
@Override
public void handle(String processInstanceId, String assignee, int flag, String reason,
String nextAssigneeKey, String nextAssigneeValue) throws BusinessException {
LOG.info("{} {} sale order process handle start! {}", processInstanceId, assignee);
Map taskVariables = new HashMap();
taskVariables.put("flag", flag);
taskVariables.put("reason", reason);
Map nextVariables = new HashMap();
nextVariables.put("flag", flag);
nextVariables.put(nextAssigneeKey, nextAssigneeValue);
processService.handleProcess(processInstanceId, assignee, true, taskVariables, nextVariables);
LOG.info("{} {} sale order process handle end! {}", processInstanceId, assignee);
LOG.info("{} sale order process next handle {} {}", processInstanceId, nextAssigneeKey, nextAssigneeValue);
}
@Override
public List> readTaskList(String assignee, int start, int offset) throws BusinessException {
return processService.readTaskList(assignee, true, start, offset);
}
@Override
public List> readHistoryTaskList(String assignee, int start, int offset) throws BusinessException {
return processService.readHistoryTaskList(assignee, true, start, offset);
}
@Override
public List> readHistoryTaskList(String processInstanceId) throws BusinessException {
return processService.readHistoryTaskList(processInstanceId);
}
@Override
public void readTrackingImage(String processInstanceId, OutputStream output) throws BusinessException {
processService.readProcessTrackingImage(processInstanceId, output);
}
}
代码链接:https://github.com/fighting-one-piece/base-platform