Spring Boot 2.0 集成 Activiti 6.0 详解

xiaoxiao2021-02-28  18

序言

工作流框架是每一个比较复杂的OA或者ERP系统都会用到的一套自动化工作流程的组件,刚开始从官网下载下来的时候看到辣么大的一个包(解压下来完整整150M左右。。。。),然后再稍微建一下数据库,打开表一看,当时我就方了(整整23张表),但是没办法,自己框架要用到,早晚也要看的,只能硬着头皮撸了~

网上的资料大部分都是Activiti与Spring集成的,用的都是Activiti5的版本,但是由于我的基础框架是Spring Boot,所以只能撸一套和Spring Boot集成的框架,而且还得支持RESTful,仔细想一下,要填的坑还是不少的。

1.尝试直接使用activiti-spring-boot-starter-basic来与Spring Boot进行集成

用过Spring Boot的同学都知道Spring Boot Stater是个好东西,基于这个东东开发的组件基本上是零配置就能集成进Spring Boot里面,非常的方便,即官方所说的“开箱即用",现在有不少插件都是有这个开箱即用的版本,activiti也不例外。

当找到这个插件以后心里微微一喜,毕竟有了这个可以很简单的使用activiti,然鹅,集成之后稍微一试,控制到就无情的报错了。仔细一查控制台才发现,这个插件的最新版本是基于Activiti 6.0来做的,并不支持Spring Boot 2.0这个版本。内心一下万马奔腾。

然后找了一下Activiti 7,当然这不是Release的版本,只存在于Github里,这一个版本是基于Spring Boot 2.0来开发的,但是它并没有开箱即用的版本,所以还是放弃了,最后选择了一个折中的方法,选择了Activiti6使用与Spring集成的方式来与Spring Boot集成,虽然没有做到开箱即用,但是配置代码还是没有太多的。

2.使用activiti-spring与Spring Boot集成

Spring Boot的配置都是基于文件的,也就是说零配置文件来实现,想到这里的话我们就可以开始开工了:

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>6.0.0</version> </dependency>

先引入activiti的依赖,并且可能会用到jackson的依赖,所以一并导入。

导入依赖之后新建activiti的配置文件ActivitiConfig.java:

package tec.gomoo.oa.config; import org.activiti.engine.*; import org.activiti.spring.SpringProcessEngineConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; import java.io.IOException; /** * @author phw * @date Created in 05-09-2018 * @description */ @Configuration public class ActivitiConfig { @Bean public ProcessEngine processEngine(DataSourceTransactionManager transactionManager, DataSource dataSource) throws IOException { SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration(); //自动部署已有的流程文件 Resource[] resources = new PathMatchingResourcePatternResolver().getResources(ResourceLoader.CLASSPATH_URL_PREFIX + "processes/*.bpmn"); configuration.setTransactionManager(transactionManager); configuration.setDataSource(dataSource); configuration.setDatabaseSchemaUpdate("true"); configuration.setDeploymentResources(resources); configuration.setDbIdentityUsed(false); return configuration.buildProcessEngine(); } @Bean public RepositoryService repositoryService(ProcessEngine processEngine) { return processEngine.getRepositoryService(); } @Bean public RuntimeService runtimeService(ProcessEngine processEngine) { return processEngine.getRuntimeService(); } @Bean public TaskService taskService(ProcessEngine processEngine) { return processEngine.getTaskService(); } @Bean public HistoryService historyService(ProcessEngine processEngine) { return processEngine.getHistoryService(); } @Bean public ManagementService managementService(ProcessEngine processEngine) { return processEngine.getManagementService(); } @Bean public IdentityService identityService(ProcessEngine processEngine) { return processEngine.getIdentityService(); } }

在Config文件上打上@Configuration注解表示这是一个自动配置文件。

首先配置一下activiti流程引擎ProcessEngine的配置类SpringProcessEngineConfiguration,这一个类是activiti和Spring集成的关键类,这个类需要我们注入两个东西,一个是数据源DataSource,一个是数据源的事务管理器DataSourceTransactionManager,这两个东西都可以通过Spring自动注入的东西。

然后把已有的流程文件设置到Configuration里面,在服务启第一次启动时就会自动创建那23张数据库的表,并且部署bpmn文件。生成ProcessEngine后就可以生成那常用几大服务了,像RepositoryService/RuntimeService/TaskService等等。

然后我们再来测试一下:

package tec.gomoo.oa.config; /** * @author phw * @date Created in 05-14-2018 * @description */ @Slf4j @Service @Transactional public class ActivitiService { private final RuntimeService runtimeService; private final TaskService taskService; private final HistoryService historyService; private final RepositoryService repositoryService; @Autowired public ActivitiService(RuntimeService runtimeService, TaskService taskService, HistoryService historyService, RepositoryService repositoryService) { this.runtimeService = runtimeService; this.taskService = taskService; this.historyService = historyService; this.repositoryService = repositoryService; } public ProcessDefinition deployProcess(MultipartFile bpmn, String path) throws IOException { if (BaseUtils.isNullOrEmpty(bpmn) || BaseUtils.isNullOrEmpty(path)) { return null; } //上传文件到processes File file = new File(path + bpmn.getOriginalFilename()); bpmn.transferTo(file); String resource = ResourceLoader.CLASSPATH_URL_PREFIX + bpmn.getOriginalFilename(); Deployment deployment = repositoryService.createDeployment().addClasspathResource(resource).deploy(); log.info("Process [" + deployment.getName() + "] deployed successful"); return repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult(); } public ProcessInstance startProcess(String key) { if (BaseUtils.isNullOrEmpty(key)) { return null; } return runtimeService.startProcessInstanceByKey(key); } public List<TaskInfo> getTasksByAssignee(String assignee) { if (BaseUtils.isNullOrEmpty(assignee)) { return null; } List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list(); if (BaseUtils.isNullOrEmpty(tasks)) { return null; } List<TaskInfo> infos = new ArrayList<>(); for (Task task: tasks) { infos.add(new TaskInfo(task.getId(), task.getName())); } return infos; } public List<TaskInfo> getTasksByGroup(String group) { if (BaseUtils.isNullOrEmpty(group)) { return null; } List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup(group).list(); if (BaseUtils.isNullOrEmpty(tasks)) { return null; } List<TaskInfo> infos = new ArrayList<>(); for (Task task : tasks) { infos.add(new TaskInfo(task.getId(), task.getName())); } return infos; } public List<TaskInfo> getTasks(String assigneeOrGroup) { if (BaseUtils.isNullOrEmpty(assigneeOrGroup)) { return null; } List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(assigneeOrGroup).list(); if (BaseUtils.isNullOrEmpty(tasks)) { return null; } List<TaskInfo> infos = new ArrayList<>(); for (Task task : tasks) { infos.add(new TaskInfo(task.getId(), task.getName())); } return infos; } public void completeTask(String taskId, Object item) { Map<String, Object> map = BaseUtils.object2ConditionMap(item); if (BaseUtils.isNullOrEmpty(taskId) || BaseUtils.isNullOrEmpty(map)) { log.error("Params cannot be empty"); throw new RuntimeException("Params cannot be empty"); } taskService.complete(taskId, map); } public void completeTask(String taskId) { if (BaseUtils.isNullOrEmpty(taskId)) { log.error("Param taskId cannot be empty"); return; } taskService.complete(taskId); } public static class TaskInfo { private String id; private String name; public TaskInfo(String id, String name) { this.id = id; this.name = name; } public void setId(String id) { this.id = id; } public String getId() { return id; } public void setName(String name) { this.name = name; } public String getName() { return name; } } }

在Junit中进行测试,若没有报错就说明我们集成完成了。

下一步就是在Activiti中统一用户管理,不使用它自带的比较简陋的用户管理。

(未完待续...)

转载请注明原文地址: https://www.6miu.com/read-2629667.html

最新回复(0)