activiti 7.0.0.SR1+springboot 2.0.4.RELEASE
文章目录
1、 idea中安装activiti的插件
2、引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<activiti.version>7.0.0.SR1</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>${activiti.version}</version>
<exclusions>
<exclusion>
<groupId>org.activiti.core.common</groupId>
<artifactId>activiti-spring-identity</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.properties中增加配置
#表示启动时检查数据库表,不存在则创建
spring.activiti.database-schema-update=true
#表示哪种情况下使用历史表,这里配置为full表示全部记录历史,方便绘制流程图
spring.activiti.history-level=full
#true表示使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表
spring.activiti.db-history-used=true
3、画流程的bpmn图,其实就是设计中的活动图
4、25张表
5、核心service
RuntimeService
TaskService
HistoryService
RepositoryService
6、启动流程并自动完成第一步
public String startProcess(ProcessDealDto processDealDto) {
ProcessInstance instance = runtimeService.startProcessInstanceByKey(WorkFlowConstant.PROCESS_WORKTICKET_ID);
//验证是否启动成功
//通过查询正在运行的流程实例来判断
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
//根据流程实例ID来查询
List<ProcessInstance> 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<String, Object> map = new HashMap<String, Object>(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;
}
7、节点处理
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<HistoricTaskInstance> 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<String, VariableInstance> variables = runtimeService.getVariableInstances(currentTask.getExecutionId());
String myActivityId = null;
List<HistoricActivityInstance> 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<SequenceFlow> oriSequenceFlows = new ArrayList<SequenceFlow>();
oriSequenceFlows.addAll(flowNode.getOutgoingFlows());
//清理活动方向
flowNode.getOutgoingFlows().clear();
//建立新方向
List<SequenceFlow> newSequenceFlowList = new ArrayList<SequenceFlow>();
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(flowNode);
newSequenceFlow.setTargetFlowElement(myFlowNode);
newSequenceFlowList.add(newSequenceFlow);
flowNode.setOutgoingFlows(newSequenceFlowList);
Map<String, Object> currentVariables = new HashMap<String, Object>();
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<String, Object> map = new HashMap<String, Object>(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());
}
}
8、历史查询
不显示起始节点和排他网关
public List<ProcessHistoryDto> getHistoryByInstance(String instanceId) {
HistoricActivityInstanceQuery historyInstanceQuery = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId);
// 查询历史节点
List<HistoricActivityInstance> historicActivityInstanceList = historyInstanceQuery.orderByHistoricActivityInstanceStartTime().asc().list();
if (ObjectUtils.isNotEmpty(historicActivityInstanceList)) {
List<ProcessHistoryDto> 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<Attachment> 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;
}
9、代办
public List<PersonToDoDto> getToDoList(String personId) {
List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(personId).list();
if(ObjectUtils.isNotEmpty(list)){
List<PersonToDoDto> 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;
}
10、重写用户权限
@Service
public class CustomUserGroupManagerImpl implements UserGroupManager{
public static List<String> roles = new ArrayList<>();
public static List<String> groups = new ArrayList<>();
public static List<String> users = new ArrayList<>();
public static Map<String,String> 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<String> getUserGroups(String s) {
return groups;
}
@Override
public List<String> getUserRoles(String s) {
String role = userRoleMap.get(s);
List<String> list = new ArrayList<>();
list.add(role);
return list;
}
@Override
public List<String> getGroups() {
return groups;
}
@Override
public List<String> getUsers() {
return users;
}
}
11、关闭activiti默认的安全校验
启动类上添加注解
@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();
}
}
12、配置activiti的数据源和线程池
@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;
}
}
13、其他问题
有时候发现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();
}
}