最近公司项目用到了activiti流程引擎,正好是自己在做,那就记录一下,方便自己后续查看,也方便需要的朋友查看。
既然已经开始看这篇代码整合文章了,我就当大家已经对activiti已经有了初步的了解了。
初始化activiti的表
activiti默认是H2数据库,这边我们使用mysql,从官方下载的文件里可以找到sql脚本,这边要注意不要选择mysql55那个版本的脚本,那是旧版本的mysql使用的(当然如果你的mysql版本低于5.5那当我没说)




另外就是,也可以不用手工运行脚本,当我们第一次在代码里使用activiti时,会自动帮我们建好表。
maven的pom.xml文件
activiti-spring-boot-starter,把版本换一下即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <!--- Activiti依赖导入 --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-rest-api</artifactId> <version>6.0.0</version> </dependency> <!--- Activiti依赖导入end --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
application.properties
最后两行日志配置是为了使用activiti时在控制台打印它的sql,方便查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server.port=5656 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true #建表规则 #flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。 #true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。 #create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。 #drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎) spring.activiti.check-process-definitions=false #自动更新数据库结构 spring.activiti.database-schema-update=true # 打印mybatis的sql日志 logging.level.com.len.mapper=DEBUG # 打印activiti的sql日志 logging.level.org.activiti.engine.impl.persistence.entity=trace |
log4j.properties
1 2 3 4 5 6 7 8 |
#set log levels log4j.rootLogger = debug , stdout , D , E #输出到控制台 log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n |
inspectProcess.bpmn20.xml
这是我的流程文件,可以通过eclipse或idea的activiti插件或者官方的流程设计器来进行设计

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/testm1583982383250" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1583982383250" name="" targetNamespace="http://www.activiti.org/testm1583982383250" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process id="inspectProcess" isClosed="false" isExecutable="true" name="inspectProcess" processType="None"> <startEvent id="_begin" name="begin"/> <userTask activiti:candidateGroups="student" activiti:exclusive="true" id="_pir" name="post inspect request"/> <sequenceFlow id="_4" sourceRef="_begin" targetRef="_pir"/> <userTask activiti:exclusive="true" id="_da" name="director approve"/> <sequenceFlow id="_6" sourceRef="_pir" targetRef="_da"/> <endEvent id="_end" name="end"/> <sequenceFlow id="_8" sourceRef="_da" targetRef="_end"/> </process> <bpmndi:BPMNDiagram xmlns="" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"> <bpmndi:BPMNPlane bpmnElement="inspectProcess"> <bpmndi:BPMNShape bpmnElement="_begin" id="Shape-_begin"> <dc:Bounds height="32.0" width="32.0" x="75.0" y="195.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_pir" id="Shape-_pir"> <dc:Bounds height="55.0" width="85.0" x="205.0" y="190.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_da" id="Shape-_da"> <dc:Bounds height="55.0" width="85.0" x="405.0" y="190.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_end" id="Shape-_end"> <dc:Bounds height="32.0" width="32.0" x="580.0" y="205.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_4" id="BPMNEdge__4" sourceElement="_2" targetElement="_3"> <di:waypoint x="107.0" y="211.0"/> <di:waypoint x="205.0" y="217.5"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_3" targetElement="_5"> <di:waypoint x="290.0" y="217.5"/> <di:waypoint x="405.0" y="217.5"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_5" targetElement="_7"> <di:waypoint x="490.0" y="217.5"/> <di:waypoint x="580.0" y="221.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions> |
在resources资源目录下新建processes目录,把资源文件放进去, src/main/resources/processes
, springboot默认是到这个文件夹里去找流程图进行部署的

ActivitiConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
import org.activiti.engine.*; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; import org.activiti.rest.service.api.RestResponseFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.converter.ContentTypeResolver; import org.springframework.messaging.converter.DefaultContentTypeResolver; import org.springframework.stereotype.Component; @Configuration public class ActivitiConfig { @Value("${spring.datasource.url}") private String url; @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driver; // activiti rest service @Bean public RestResponseFactory restResponseFactory(){ return new RestResponseFactory(); } @Bean public ContentTypeResolver contentTypeResolver(){ return new DefaultContentTypeResolver(); } // activiti core // ProcessEngine 和服务类都是线程安全的。 @Bean public ProcessEngineConfiguration processEngineConfiguration() { ProcessEngineConfiguration processEngineConfiguration = new StandaloneProcessEngineConfiguration(); // 连接数据库的配置 processEngineConfiguration.setJdbcDriver(driver); processEngineConfiguration.setJdbcUrl(url); processEngineConfiguration.setJdbcUsername(userName); processEngineConfiguration.setJdbcPassword(password); processEngineConfiguration.setAsyncExecutorActivate(true); processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); return processEngineConfiguration; } /* @Bean public ProcessEngine processEngine() { return processEngineConfiguration().buildProcessEngine(); } */ @Bean public RepositoryService repositoryService() { return processEngineConfiguration().buildProcessEngine().getRepositoryService(); } @Bean public RuntimeService runtimeService() { return processEngineConfiguration().buildProcessEngine().getRuntimeService(); } @Bean public TaskService taskService() { return processEngineConfiguration().buildProcessEngine().getTaskService(); } @Bean public FormService formService() { return processEngineConfiguration().buildProcessEngine().getFormService(); } @Bean public HistoryService historyService() { return processEngineConfiguration().buildProcessEngine().getHistoryService(); } @Bean public ManagementService managementService() { return processEngineConfiguration().buildProcessEngine().getManagementService(); } @Bean public IdentityService identityService() { return processEngineConfiguration().buildProcessEngine().getIdentityService(); } } |
LeaveProcessController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import lombok.extern.slf4j.Slf4j; import org.activiti.engine.*; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.identity.Group; import org.activiti.engine.identity.User; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.task.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @Slf4j public class LeaveProcessController { @Autowired private RuntimeService runtimeService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; @Autowired private HistoryService historyService; @Autowired private IdentityService identityService; /** * 一个示例流程 * @return */ @GetMapping("/process") public void process(){ // 先准备好用户、用户组 addUser(); addGroup(); relationUserGroup(); // 部署流程 Deployment deployment = repositoryService.createDeployment() .addClasspathResource("processes/inspectProcess.bpmn20.xml") .name("test inspect") .key("shOffice") .deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()).singleResult(); log.info("流程名称 : [" + processDefinition.getName() + "], 流程ID : [" + processDefinition.getId() + "], 流程KEY : " + processDefinition.getKey()); // 开始流程 String procId = runtimeService.startProcessInstanceByKey(processDefinition.getKey()).getId(); /*// 给一个新任务添加候选人组student Task sTask = taskService.newTask(); taskService.addCandidateGroup(sTask.getId(), "student");*/ // 获取指定用户组的 Task 列表,并使用指定用户领取这些任务 List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("student").list(); for (Task task : tasks) { System.out.println("student分组的任务: " + task.getName()); // 用户Jonathan领取任务 taskService.claim(task.getId(), "Jonathan"); } // 获取Jonathan用户的工作 Task 列表,并完成这些任务 tasks = taskService.createTaskQuery().taskAssignee("Jonathan").list(); for (Task task : tasks) { log.info("Jonathan的任务: " + task.getName()); // 完成 taskService.complete(task.getId()); } log.info("用户Jonathan的任务数量: " + taskService.createTaskQuery().taskAssignee("Jonathan").count()); // 使用 HistoryService 来查询指定流程实例的状态 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult(); log.info("流程结束时间: " + historicProcessInstance.getEndTime()); } public void addUser(){ //先查询用户 User userInDb = identityService.createUserQuery().userId("Jonathan").singleResult(); if (userInDb == null){ User user = identityService.newUser("Jonathan"); user.setFirstName("Jonathan"); user.setLastName("chang"); user.setEmail("whatlookingfor@gmail.com"); user.setPassword("123"); //保存用户到数据库 identityService.saveUser(user); } } public void addGroup(){ Group groupInDb = identityService.createGroupQuery().groupId("student").singleResult(); if (groupInDb == null){ //创建用户组对象 Group group = identityService.newGroup("student"); group.setName("student用户组"); group.setType("ask"); //保存用户组 identityService.saveGroup(group); } } public void relationUserGroup(){ // 查询属于student用户组的用户 User userInGroup = identityService.createUserQuery().memberOfGroup("student").singleResult(); User userInDb = identityService.createUserQuery().userId("Jonathan").singleResult(); if (userInGroup == null || !userInGroup.getId().equals(userInDb.getId())){ //将用户Jonathan加入到用户组student中 identityService.createMembership("Jonathan","student"); } } } |
工程图

这样SpringBoot2.0整合activiti6示例就完成了。如果有问题欢迎留言。
+2
❤️💕👍
您好,烦请问一下,activiti的事务配置成spring来管理您这边有没有一些考虑,谢谢!
直接使用spring的事务管理器就可以控制事务的提交,回滚了,@Transactional(rollbackFor = Exception.class)
谢谢,有用
学习了。。
最近也在学流程引擎
终于找到你