Activiti學習筆記-整合SpringBoot與簡單使用

Activiti版本:7.1.0.M3.1

Spring Boot 版本:2.1.1.RELEASE

相關依賴如下:

<!-- Activiti依賴包 -->
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-engine</artifactId>
    <version>7.1.0.M3.1</version>
</dependency>

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring</artifactId>
    <version>7.1.0.M3.1</version>
</dependency>

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-image-generator</artifactId>
    <version>6.0.0</version>
</dependency>

相關配置如下:

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<String, Object> variables, String assignee,
			Map<String, Object> nextVariables) throws RuntimeException;
	
	/**
	 * 處理流程
	 * @param processInstanceId
	 * @param assignee
	 * @param taskVariables
	 * @param nextVariables
	 * @throws RuntimeException
	 */
	public void handleProcess(String processInstanceId, String assignee, boolean isCandidateUser,
			Map<String, Object> taskVariables, Map<String, Object> nextVariables) throws RuntimeException;
	
	/**
	 * 讀取任務列表
	 * @param assignee
	 * @param isCandidateUser
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws RuntimeException
	 */
	public List<Map<String, Object>> readTaskList(String assignee, boolean isCandidateUser, 
			int firstResult, int maxResults) throws RuntimeException;
	
	/**
	 * 讀取歷史任務列表
	 * @param assignee
	 * @param isCandidateUser
	 * @param firstResult
	 * @param maxResults
	 * @return
	 * @throws RuntimeException
	 */
	public List<Map<String, Object>> readHistoryTaskList(String assignee, boolean isCandidateUser, 
			int firstResult, int maxResults) throws RuntimeException;

	/**
	 * 讀取流程實例的歷史任務
	 * @param processInstanceId
	 * @return
	 * @throws RuntimeException
	 */
	public List<Map<String, Object>> readHistoryTaskList(String processInstanceId) throws RuntimeException;
	
	/**
	 * 讀取流程追蹤圖
	 * @param processInstanceId
	 * @param output
	 * @throws RuntimeException
	 */
	public void readProcessTrackingImage(String processInstanceId, OutputStream output) throws RuntimeException;
	
}
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<String, Object> variables, String assignee,
			Map<String, Object> nextVariables) throws RuntimeException {
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);  
	    List<Task> 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<String, Object> taskVariables, Map<String, Object> 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<Map<String, Object>> 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<Task> taskList = taskQuery.listPage(firstResult, maxResults);
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		for (int i = 0, len = taskList.size(); i < len; i++) {
			resultList.add(ReflectUtils.convertObjectToObjectMap(taskList.get(i)));
		}
		return resultList;
	}
	
	@Override
	public List<Map<String, Object>> 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<HistoricTaskInstance> taskInstanceList = taskInstanceQuery.listPage(firstResult, maxResults);
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		for (int i = 0, len = taskInstanceList.size(); i < len; i++) {
			resultList.add(ReflectUtils.convertObjectToObjectMap(taskInstanceList.get(i)));
		}
		return resultList;
	}
	
	@Override
	public List<Map<String, Object>> readHistoryTaskList(String processInstanceId) throws RuntimeException {
		List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
			.processInstanceId(processInstanceId).orderByTaskCreateTime().asc().list();
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		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<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
			.processInstanceId(processInstanceId).orderByHistoricActivityInstanceId().asc().list();
		// 已執行歷史節點
		List<String> executedHistoricActivityIdList = new ArrayList<String>();
		historicActivityInstanceList.forEach(historicActivityInstance -> {
				LOG.info("historic activity name {}", historicActivityInstance.getActivityName());
				executedHistoricActivityIdList.add(historicActivityInstance.getActivityId());
			});
		BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionEntity.getId());
		// 已執行Flow
		List<String> 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<String> getExecutedFlowIdList(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstanceList) {
		List<String> executedFlowIdList = new ArrayList<String>();
		for(int i = 0, len = historicActivityInstanceList.size(); i < len - 1; i++) {
			HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(i);
			FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(historicActivityInstance.getActivityId());
			List<SequenceFlow> 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<String, Object> variables = new HashMap<String, Object>();
	    variables.put("saleUser", saleUserAccount);
	    variables.put("saleOrder", saleOrderNo);
	    Map<String, Object> nextVariables = new HashMap<String, Object>();
	    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<String, Object> taskVariables = new HashMap<String, Object>();
		taskVariables.put("flag", flag);
		taskVariables.put("reason", reason);
		Map<String, Object> nextVariables = new HashMap<String, Object>();
		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<Map<String, Object>> readTaskList(String assignee, int start, int offset) throws BusinessException {
		return processService.readTaskList(assignee, true, start, offset);
	}

	@Override
	public List<Map<String, Object>> readHistoryTaskList(String assignee, int start, int offset) throws BusinessException {
		return processService.readHistoryTaskList(assignee, true, start, offset);
	}

	@Override
	public List<Map<String, Object>> 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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章