activiti 7.0.0.SR1+springboot 2.0.4.RELEASE
org.springframework.boot
spring-boot-starter-parent
2.0.4.RELEASE
7.0.0.SR1
org.springframework.boot
spring-boot-starter-web
com.baomidou
mybatisplus-spring-boot-starter
1.0.5
com.baomidou
mybatis-plus
3.1.0
com.alibaba
druid
1.1.16
mysql
mysql-connector-java
5.1.35
org.activiti
activiti-spring-boot-starter
${activiti.version}
org.activiti.core.common
activiti-spring-identity
application.properties中增加配置
#表示启动时检查数据库表,不存在则创建
spring.activiti.database-schema-update=true
#表示哪种情况下使用历史表,这里配置为full表示全部记录历史,方便绘制流程图
spring.activiti.history-level=full
#true表示使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表
spring.activiti.db-history-used=true
RuntimeService
TaskService
HistoryService
RepositoryService
public String startProcess(ProcessDealDto processDealDto) {
ProcessInstance instance = runtimeService.startProcessInstanceByKey(WorkFlowConstant.PROCESS_WORKTICKET_ID);
//验证是否启动成功
//通过查询正在运行的流程实例来判断
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
//根据流程实例ID来查询
List runningList = processInstanceQuery.processInstanceId(instance.getProcessInstanceId()).list();
logger.debug(LogFormatter.toMsg("start process", "instance"), runningList);
String instanceId = instance.getId();
//设置处理人
Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
if (task != null) {
//自动完成第一步
Map map = new HashMap(2);
map.put("check", 1);
map.put("personId", processDealDto.getPersonId());
taskService.setAssignee(task.getId(), processDealDto.getCurrentPersonId());
taskService.complete(task.getId(), map);
task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
taskService.setAssignee(task.getId(), processDealDto.getPersonId());
} else {
throw new BusinessException(WorkTaskErrorCode.WORK_TASK_START_PROCESS_ERROR);
}
// 返回流程ID
return instanceId;
}
public void auditProcess(ProcessDealDto processDealDto) {
Task task = null;
if (ObjectUtils.isNotEmpty(processDealDto.getInstanceId())) {
task = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();
} else if (ObjectUtils.isNotEmpty(processDealDto.getTaskId())) {
task = taskService.createTaskQuery().taskId(processDealDto.getTaskId()).singleResult();
}
if (task == null) {
throw new BusinessException(WorkTaskErrorCode.WORK_TASK_BACK_PROCESS_EMPTY_ERROR);
}
if (WorkFlowConstant.AUDIT_PASS.equals(processDealDto.getCheck())) {
dealProcess(task, processDealDto);
} else {
backProcess(task, processDealDto);
}
}
/**
* 退回到上一节点
*
* @param task
* @param processDealDto
*/
private void backProcess(Task task, ProcessDealDto processDealDto) {
List htiList = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processDealDto.getInstanceId())
.orderByTaskCreateTime()
.desc()
.list();
if (ObjectUtils.isEmpty(htiList) || htiList.size() < 2) {
return;
}
HistoricTaskInstance myTask = htiList.get(1);
String myTaskId = myTask.getId();
if (null == myTaskId) {
throw new BusinessException(WorkTaskErrorCode.WORK_TASK_BACK_PROCESS_USER_ERROR);
}
String processDefinitionId = myTask.getProcessDefinitionId();
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
//变量
// Map variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
String myActivityId = null;
List haiList = historyService.createHistoricActivityInstanceQuery()
.executionId(myTask.getExecutionId()).finished().list();
for (HistoricActivityInstance hai : haiList) {
if (myTaskId.equals(hai.getTaskId())) {
myActivityId = hai.getActivityId();
break;
}
}
FlowNode myFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(myActivityId);
Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
String activityId = execution.getActivityId();
// logger.warn("------->> activityId:" + activityId);
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
//记录原活动方向
List oriSequenceFlows = new ArrayList();
oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
//清理活动方向
flowNode.getOutgoingFlows().clear();
//建立新方向
List newSequenceFlowList = new ArrayList();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(flowNode);
newSequenceFlow.setTargetFlowElement(myFlowNode);
newSequenceFlowList.add(newSequenceFlow);
flowNode.setOutgoingFlows(newSequenceFlowList);
Map currentVariables = new HashMap();
currentVariables.put("check", 0);
currentVariables.put("dealMsg", processDealDto.getDealMsg());
currentVariables.put("personId", processDealDto.getPersonId());
taskService.createAttachment("", task.getId(), processDealDto.getInstanceId(), "dealMsg", processDealDto.getDealMsg(), "");
//完成任务
taskService.complete(task.getId(), currentVariables);
//恢复原方向
flowNode.setOutgoingFlows(oriSequenceFlows);
Task nextTask = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();
if(nextTask!=null) {
taskService.setAssignee(nextTask.getId(), myTask.getAssignee());
}
}
/**
* 正向流程
*
* @param task
* @param processDealDto
*/
private void dealProcess(Task task, ProcessDealDto processDealDto) {
Map map = new HashMap(2);
map.put("check", processDealDto.getCheck());
map.put("personId", processDealDto.getPersonId());
map.put("dealMsg", processDealDto.getDealMsg());
task.setDescription(WorkFlowStatus.getDescriptionByIndex(processDealDto.getNodeType()));
String taskId = task.getId();
taskService.createAttachment("", taskId, processDealDto.getInstanceId(), "dealMsg", processDealDto.getDealMsg(), "");
taskService.complete(taskId, map);
//设置处理人,将流程流转到下一个人
Task nextTask = taskService.createTaskQuery().processInstanceId(processDealDto.getInstanceId()).singleResult();
if(nextTask!=null) {
taskService.setAssignee(nextTask.getId(), processDealDto.getPersonId());
}
}
不显示起始节点和排他网关
public List getHistoryByInstance(String instanceId) {
HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId);
// 查询历史节点
List historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
if (ObjectUtils.isNotEmpty(historicActivityInstanceList)) {
List historyDtos = new ArrayList<>();
Integer lastNodeId = null;
ProcessHistoryDto lastHistoryNode = null;
for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
if(activityInstance.getActivityName().equals("StartEvent") || activityInstance.getActivityName().equals("ExclusiveGateway")){
continue;
}
ProcessHistoryDto historyDto = new ProcessHistoryDto();
historyDto.setActivitId(activityInstance.getActivityId());
historyDto.setDealPersonID(activityInstance.getAssignee());
historyDto.setDealTime(activityInstance.getEndTime());
Integer nowNodeId = WorkFlowNodeEnum.getIndexByName(activityInstance.getActivityId());
historyDto.setNodeId(nowNodeId);
historyDto.setCheck(true);
//判断是否为驳回
if(lastNodeId != null && nowNodeId < lastNodeId){
lastHistoryNode.setCheck(false);
}else if(lastNodeId != null && WorkFlowNodeEnum.WORK_PERMITER_CHECK.getIndex().equals(lastNodeId)
&& WorkFlowNodeEnum.FINISH.getIndex().equals(nowNodeId)){
//从许可人直接驳回
lastHistoryNode.setCheck(false);
}
if(!"EndEvent".equals(activityInstance.getActivityName())) {
List attachmentList = taskService.getTaskAttachments(activityInstance.getTaskId());
if (ObjectUtils.isNotEmpty(attachmentList)) {
historyDto.setAttachment(attachmentList.get(0).getDescription());
}
historyDto.setDealPersonName(getPersonNameAndNoById(activityInstance.getAssignee()));
}
lastNodeId = nowNodeId;
lastHistoryNode = historyDto;
//没有结束时间,表示当前正处于该节点,历史中不展示,但是要用这个节点来判断是否是驳回
if(ObjectUtils.isEmpty(activityInstance.getEndTime())){
continue;
}
historyDtos.add(historyDto);
}
return historyDtos;
}
return null;
}
public List getToDoList(String personId) {
List list = taskService.createTaskQuery().taskCandidateOrAssigned(personId).list();
if(ObjectUtils.isNotEmpty(list)){
List personToDoDtos = new ArrayList<>();
for(Task task : list){
PersonToDoDto personToDoDto = new PersonToDoDto();
personToDoDto.setInstanceId(task.getProcessInstanceId());
personToDoDto.setTaskId(task.getId());
personToDoDtos.add(personToDoDto);
}
return personToDoDtos;
}
return null;
}
@Service
public class CustomUserGroupManagerImpl implements UserGroupManager{
public static List roles = new ArrayList<>();
public static List groups = new ArrayList<>();
public static List users = new ArrayList<>();
public static Map userRoleMap = new HashMap<>();
static {
roles.add("workCreate");
roles.add("workPermit");
roles.add("workLeader");
groups.add("workGroupA");
users.add("admin");
users.add("laowang");
users.add("xiaofang");
userRoleMap.put("admin", "workCreate");
userRoleMap.put("laowang", "workPermit");
userRoleMap.put("xiaofang", "workLeader");
}
@Override
public List getUserGroups(String s) {
return groups;
}
@Override
public List getUserRoles(String s) {
String role = userRoleMap.get(s);
List list = new ArrayList<>();
list.add(role);
return list;
}
@Override
public List getGroups() {
return groups;
}
@Override
public List getUsers() {
return users;
}
}
启动类上添加注解
@EnableAutoConfiguration(exclude = {org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class})
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().logout().permitAll();
}
}
@Configuration
public class WorkFlowConfiguration{
@Autowired
private UserGroupManager userGroupManager;
@Autowired
private DataSource dataSource;
private int corePoolSize = 10;
private int maxPoolSize = 30;
private int keepAliveSeconds = 300;
private int queueCapacity = 300;
@Bean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(
PlatformTransactionManager transactionManager) throws IOException {
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
configuration.setDataSource(dataSource);
configuration.setTransactionManager(transactionManager);
SpringAsyncExecutor asyncExecutor = new SpringAsyncExecutor();
asyncExecutor.setTaskExecutor(workFlowAsync());
configuration.setAsyncExecutor(asyncExecutor);
configuration.setDatabaseSchemaUpdate("true");
configuration.setUserGroupManager(userGroupManager);
configuration.setHistoryLevel(HistoryLevel.FULL);
configuration.setDbHistoryUsed(true);
return configuration;
}
@Primary
@Bean("workFlowTaskExecutor")
public ThreadPoolTaskExecutor workFlowAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
executor.setQueueCapacity(queueCapacity);
executor.setThreadNamePrefix("workFlowTaskExecutor-");
executor.initialize();
return executor;
}
}
有时候发现application.properties中的配置不起作用
@Configuration
public class InitConfigTest implements CommandLineRunner {
@Autowired
private ProcessEngine processEngine;
@Override
public void run(String... args) throws Exception {
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.name("workTask")
.addClasspathResource("processes/workTask.bpmn")
// .addClasspathResource("repository/TestProcess.png")
.deploy();
}
}