1 SpringBoot-Activiti技术
1.1 技术介绍
Activiti 7是Alfresco经过实战考验的Activiti工作流引擎的演变,完全被采用在云环境中运行。它是根据 Cloud Native 应用程序概念构建的,与之前的Activiti版本在架构方面有所不同。基于我的理解,帮助开发人员进行流程控制,而工作流的概念就是一个制度的体现,管理体系的体现。举例来讲:小到家庭琐事,现在有个老李想和朋友,可是他身上没有钱,他需要得到老婆的同意,然后再由老婆拨款,才能出门和朋友吃饭。更一步案例,现在老李正在读小学,马上要考试了,可是他今天生病了,需要请假,但是这次考试又很重要,他不想放弃。这时就是学校的管理制度起作用了,老师不仅同意了老李的病假,还为老李破例开通第二套试卷考试,老李在休息得当的情况下,顺利的完成了考试,考出高分。而上升到公司,行业管理等等,其实也是人与人之间的确认信息。
· 较多使用场合
订单、报价处理、合同审核、客户电话处理、供应链管理。土地开发审核、资源开发审核、人力资源、办公软件之类。
1.2 技术注意点
1.2.1 流程图
- 流程图必须有一个或多个默认流
- 流程判断必须带有参数条件
- 流程图的权限控制:assignee(不包括)、candidateUsers(哪些用户)、candidateGroups(哪些角色)
1.2.2 流程图ID
这个一定要修改,不能出现同名,否则就会出现这个错误。
The deployment contains process definitions with the same key (process id attribute), this is not….
https://blog.csdn.net/qq_41520636/article/details/118304495
1.3 技术具体demo文件路径
1.4 demo的UML图
1.5 demo的技术代码实现
1.5.1 环境准备
SpringBoot:2.0.4.RELEASEJDK:1.8Activiti:7.1.0.M2MySQL:8.0.21开发软件:IDEA流程插件:actiBPM
1.5.2 安装插件
Files → Settings → Plugins → 搜索actiBPM → 下载安装 → 搜索JBoss jBPM → 下载安装
1.5.3 插件试玩
1.5.4 创建bpnmFile文件

创建好后,可以通过修改文件后缀名查看里面的代码
打开team01.xml
<?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:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:yaoqiang="http://bpmn.sourceforge.net" expressionLanguage="http://www.w3.org/1999/XPath" id="m1544167269809" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"><process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"><extensionElements><yaoqiang:description/><yaoqiang:pageFormat height="841.8897637795276" imageableHeight="831.8897637795276" imageableWidth="588.1102362204724" imageableX="5.0" imageableY="5.0" orientation="0" width="598.1102362204724"/><yaoqiang:page background="#FFFFFF" horizontalCount="1" verticalCount="1"/></extensionElements><startEvent id="_2" isInterrupting="true" name="StartEvent" parallelMultiple="false"/><userTask activiti:candidateGroups="activitiTeam" activiti:exclusive="true" completionQuantity="1" id="_3" implementation="##unspecified" isForCompensation="false" name="填写申请单" startQuantity="1"/><userTask activiti:candidateGroups="activitiTeam" activiti:exclusive="true" completionQuantity="1" id="_4" implementation="##unspecified" isForCompensation="false" name="审核" startQuantity="1"/><endEvent id="_5" name="EndEvent"/><sequenceFlow id="_6" sourceRef="_2" targetRef="_3"/><sequenceFlow id="_7" sourceRef="_3" targetRef="_4"/><sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/></process><bpmndi:BPMNDiagram 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="myProcess_1"><bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"><omgdc:Bounds height="32.0" width="32.0" x="65.0" y="80.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"><omgdc:Bounds height="55.0" width="85.0" x="170.0" y="115.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"><omgdc:Bounds height="55.0" width="85.0" x="310.0" y="155.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"><omgdc:Bounds height="32.0" width="32.0" x="505.0" y="220.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/></bpmndi:BPMNLabel></bpmndi:BPMNShape><bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_2" targetElement="_3"><omgdi:waypoint x="97.0" y="96.0"/><omgdi:waypoint x="170.0" y="142.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="18.96" width="6.0" x="130.5" y="109.77"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_3" targetElement="_4"><omgdi:waypoint x="255.0" y="142.5"/><omgdi:waypoint x="310.0" y="182.5"/><bpmndi:BPMNLabel><omgdc:Bounds height="18.96" width="6.0" x="279.5" y="153.02"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge><bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5"><omgdi:waypoint x="395.0" y="182.5"/><omgdi:waypoint x="505.0" y="236.0"/><bpmndi:BPMNLabel><omgdc:Bounds height="18.96" width="6.0" x="447.0" y="199.77"/></bpmndi:BPMNLabel></bpmndi:BPMNEdge></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></definitions>
1.5.5 创建activiti特有数据库
因为利用的是springboot,就不用使用xml配置,还要代码注入后,才能启动。
启动流程
yml配置 → ProcessEngine(流程引擎)→ RuntimeService(流程运行管理类)
→ TaskService(流程运行管理类)→ RepositoryService(资源管理类)→ HistoryService(历史管理类)→ ManagementService(引擎管理类)在此之前,你需要先知道Activiti7属于高版本,已经舍弃掉了三张表,这三张就是权限管理,由于过于简单舍弃,选择Spring Security来控制权限。你必须在你的本地创建一个activiti的数据库,来存放新增的表。
2 实战例子
2.1 入门案例
2.1 创建pom
<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><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><mysql.version>8.0.21</mysql.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- activiti 自动建表 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.1.0.M2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Thymeleaf依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies><build><finalName>my-springboot-activiti-demo</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
2.2 准备application.yml
spring:datasource:url: jdbc:mysql://localhost:3306/activitiusername: rootpassword: 123hikari:data-source-properties:useSSL: falseserverTimezone: GMT+8useUnicode: truecharacterEncoding: utf8# 这个必须要加,否则 Activiti 自动建表会失败nullCatalogMeansCurrent: trueactiviti:# 保存历史数据级别设置为full最高级别,便于历史数据的追溯history-level: fulldb-history-used: true# 不启动检查activiti数据库版本是否匹配,提升应用启动效率database-schema-update: false#自动检查、部署流程定义文件check-process-definitions: true#流程定义文件存放目录,要具体到某个目录process-definition-location-prefix: classpath:/processes/# process-definition-location-suffixes: #流程文件格式# - **.bpmn20.xml# - **.bpmn
2.3 创建Spring Security的授权用户
@Slf4j@Configuration@EnableWebSecuritypublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {@Autowired@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();}/*** spring security 高版本自带* @return*/@Beanprotected UserDetailsService myUserDetailsService() {InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();// 四个普通用户,一个管理员String[][] usersGroupsAndRoles = {{"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},{"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},{"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},{"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},{"admin", "password", "ROLE_ACTIVITI_ADMIN"}};for (String[] user : usersGroupsAndRoles) {List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));log.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),authoritiesStrings.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList())));}return inMemoryUserDetailsManager;}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}
2.4 创建一个授权认证
注意:这只是测试环境,真是环境并不是怎么操作,还是需要用户正常登录授权,这里只是写了死值,方便测试。
@Component@RequiredArgsConstructor(onConstructor_ = @Autowired)public class SecurityUtil {private final UserDetailsService userDetailsService;public void logInAs(String username) {UserDetails user = userDetailsService.loadUserByUsername(username);if (user == null) {throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");}SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return user.getAuthorities();}@Overridepublic Object getCredentials() {return user.getPassword();}@Overridepublic Object getDetails() {return user;}@Overridepublic Object getPrincipal() {return user;}@Overridepublic boolean isAuthenticated() {return true;}@Overridepublic void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {}@Overridepublic String getName() {return user.getUsername();}}));org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);}}
2.5 测试代码
@RunWith(SpringRunner.class)@SpringBootTestpublic class SpringBootDemoActivitiApplicationTests {@Autowiredprivate ProcessRuntime processRuntime; // 流程引擎的抽象,可以获取所有的服务/*** 列出所有流程定义*/@Testpublic void contextLoads() {// 调用授权securityUtil.logInAs("salaboy");// 查询十条流程实例信息Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));processDefinitionPage.getContent().forEach(System.out::println);}}
2.6 结果

查询出来的结果
这里查询出的数据,对应的数据库中的act_re_procdef(流程定义数据表)。
其实,springboot只要把pom依赖导入,yml数据源配置好后,然后启动springbootapplication服务,数据库就能自动创建,而我们选择使用一个小案例,能够看到具体的调用流程实现。
当我启动springboot服务时,以下四张表会新增数据。
- act_ge_property(属性数据表)

- act_re_deployment(部署信息表)

- act_ge_bytearray(二进制数据表)

- act_re_procdef(流程定义数据表)
2.2 简单审批案例

2.2.1 发起请假申请流程
@Testpublic void testProcessInstance(){// 流程名String key = "bohui";// 申请人String username = "zhangsan";HashMap<String, Object> map = new HashMap<>();// 启动流程实例时给变量赋值map.put("assignee1", username);// 启动流程,发送请假请求ActivitiUtil.startProcessInstanceWithVariables(username, key,"请假", map);}
/*** 启动流程* @param username 用户名* @param processKey 流程 Key => 对应bpmn文件里的id* @param processName 流程实例名* @param variables 变量map*/public static void startProcessInstanceWithVariables(String username,String processKey, String processName,HashMap<String,Object> variables) {// Security 授权用户(这里的代码上面的授权认证一样)activitiUtil.securityUtil.logInAs(username);// 创建一个运行时流程,并启动该流程ProcessInstance processInstance = activitiUtil.processRuntime.start(ProcessPayloadBuilder.start() // 启动流程.withProcessDefinitionKey(processKey) // 流程运行时定义流程实例.withName(processName) // 流程事务,要做什么.withVariables(variables) // 流程变量,一些额外的属性.build());logger.info("流程实例启动成功: " + processInstance);}
执行结果:
流程实例启动成功: ProcessInstance{id='1bac6242-d8e3-11eb-abf7-04d3b0ccfa07', name='请假', processDefinitionId='bohui:1:e2f71a3c-d8bf-11eb-9c08-04d3b0ccfa07', processDefinitionKey='bohui', parentId='null', initiator='zhangsan', startDate=Tue Jun 29 22:05:49 CST 2021, businessKey='null', status=RUNNING, processDefinitionVersion='1'}**数据库新增表**
- act_hi_actinst(历史节点表)

- act_hi_detail(历史详情表)

- act_hi_identitylink(历史流程人员表)

- act_hi_procinst(历史流程实例表)

- act_hi_taskinst(历史任务实例表)

- act_hi_varinst(历史变量表)

- act_ru_execution(运行时流程执行实例表)

- act_ru_identitylink(运行时流程人员表)

- act_ru_task(运行时任务节点表)

- act_ru_variable(运行时流程变量数据表)
2.2.2 获取所有流程定义
@Testpublic void testQueryTask(){String assignee = "zhangsan";// 获取所有流程定义ActivitiUtil.printTaskList(assignee, 0, 10);}
/*** 打印指派人所有任务** @param assignee 指派人* @param startNum 分页开始下标* @param endNum 分页结束下标*/public static void printTaskList(String assignee, Integer startNum, Integer endNum) {// 获取所有任务listPage<org.activiti.api.task.model.Task> tasks = getTaskList(assignee, startNum, endNum);// 任务的总数大于0if (tasks.getTotalItems() > 0) {// 有任务时,完成任务for (org.activiti.api.task.model.Task task : tasks.getContent()) {logger.info("任务: " + task);}}}
@Autowiredprivate CustomTaskRuntimeImpl customTaskRuntimeImpl;private static ActivitiUtil activitiUtil;/*** 查询当前指派人的任务** @param assignee 指派人* @param startNum 分页开始下标* @param endNum 分页结束下标* @return 任务list*/public static Page<org.activiti.api.task.model.Task> getTaskList(String assignee, Integer startNum, Integer endNum) {// 授权用户activitiUtil.securityUtil.logInAs(assignee);//return activitiUtil.customTaskRuntimeImpl.tasks(Pageable.of(startNum, endNum));}
@PreAuthorize("hasRole('ACTIVITI_USER')") // 控制一个方法需要权限调用@Componentpublic class CustomTaskRuntimeImpl implements TaskRuntime {// 安全管理器private final SecurityManager securityManager;// 流程运行管理类private final TaskService taskService;// API任务转换private final APITaskConverter taskConverter;/**** @param pageable 可分页*/@Overridepublic Page<Task> tasks(Pageable pageable) {// 获取认证用户idString authenticatedUserId = securityManager.getAuthenticatedUserId();// 认证用户id不为空的场合if (authenticatedUserId != null && !authenticatedUserId.isEmpty()) {// 获取认证用户组List<String> userGroups = securityManager.getAuthenticatedUserGroups();// 分页的任务return tasks(pageable,TaskPayloadBuilder.tasks().withAssignee(authenticatedUserId).withGroups(userGroups).build());}throw new IllegalStateException("You need an authenticated user to perform a task query");}/**** @param pageable 可分页* @param getTasksPayload 获取多个任务负载*/@Overridepublic Page<Task> tasks(Pageable pageable,GetTasksPayload getTasksPayload) {// 创建任务队列TaskQuery taskQuery = taskService.createTaskQuery();// 任务负载不为空的场合if (getTasksPayload == null) {// 生成任务负载getTasksPayload = TaskPayloadBuilder.tasks().build();}// 获取认证用户IDString authenticatedUserId = securityManager.getAuthenticatedUserId();// 认证用户ID不为空的场合if (authenticatedUserId != null && !authenticatedUserId.isEmpty()) {// 获取认证用户组List<String> userGroups = securityManager.getAuthenticatedUserGroups();// 任务负载设置指派人IDgetTasksPayload.setAssigneeId(authenticatedUserId);// 任务负载设置用户组getTasksPayload.setGroups(userGroups);} else {throw new IllegalStateException("You need an authenticated user to perform a task query");}// 按照分配组 OR 指派人查询taskQuery = taskQuery.or().taskCandidateOrAssigned(getTasksPayload.getAssigneeId(),getTasksPayload.getGroups())// .taskOwner(authenticatedUserId).endOr();// 获取流程实例ID不为空的场合if (getTasksPayload.getProcessInstanceId() != null) {// 为任务队列设置流程实例IDtaskQuery = taskQuery.processInstanceId(getTasksPayload.getProcessInstanceId());}// 获取父任务ID不为空的场合if (getTasksPayload.getParentTaskId() != null) {// 为任务队列设置父任务IDtaskQuery = taskQuery.taskParentTaskId(getTasksPayload.getParentTaskId());}// 将任务队列里的分页list转换为任务listList<Task> tasks = taskConverter.from(taskQuery.listPage(pageable.getStartIndex(),pageable.getMaxItems()));// 返回分页实现类return new PageImpl<>(tasks,Math.toIntExact(taskQuery.count()));}}
Activiti 开发案例之 API 映射 SQL 查询
https://www.imooc.com/article/279591
查询结果:
任务: TaskImpl{id=’1bae8529-d8e3-11eb-abf7-04d3b0ccfa07’, owner=’null’, assignee=’zhangsan’, name=’发起’, description=’null’, createdDate=Tue Jun 29 22:05:49 CST 2021, claimedDate=null, dueDate=null, priority=50, processDefinitionId=’bohui:1:e2f71a3c-d8bf-11eb-9c08-04d3b0ccfa07’, processInstanceId=’1bac6242-d8e3-11eb-abf7-04d3b0ccfa07’, parentTaskId=’null’, formKey=’null’, status=ASSIGNED, processDefinitionVersion=null, businessKey=null, taskDefinitionKey=_3}
2.2.3 进入审批阶段(指定审批人)
@Testpublic void testCompleteTask(){// 申请人String assignee = "zhangsan";HashMap<String, Object> map = new HashMap<>();// 完成任务时同时指定之后流程的指派人(审批人)map.put("assignee2", "lisi");// 根据变量条件完成对应任务ActivitiUtil.completeTaskWithVariables(assignee, map);}
/*** 完成任务** @param assignee 指派人* @param variables 变量map*/public static void completeTaskWithVariables(String assignee, HashMap<String,Object> variables) {// 获取默认前十条任务Page<org.activiti.api.task.model.Task> tasks = getTaskList(assignee, 0, 10);// 任务总数大于零的场合if (tasks.getTotalItems() > 0) {// 有任务时,完成任务for (org.activiti.api.task.model.Task task : tasks.getContent()) {System.out.println(task);// 完成任务activitiUtil.taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).withVariables(variables).build());logger.info(assignee + "完成任务");}}}
执行结果:
Logged in as: zhangsan
TaskImpl{id=’1bae8529-d8e3-11eb-abf7-04d3b0ccfa07’, owner=’null’, assignee=’zhangsan’, name=’发起’, description=’null’, createdDate=Tue Jun 29 22:05:49 CST 2021, claimedDate=null, dueDate=null, priority=50, processDefinitionId=’bohui:1:e2f71a3c-d8bf-11eb-9c08-04d3b0ccfa07’, processInstanceId=’1bac6242-d8e3-11eb-abf7-04d3b0ccfa07’, parentTaskId=’null’, formKey=’null’, status=ASSIGNED, processDefinitionVersion=null, businessKey=null, taskDefinitionKey=_3}
2021-06-30 00:40:35.753 INFO 16368 —- [ main] c.z.a.utils.ActivitiUtil : zhangsan完成任务
2.2.4 进入审批阶段(审批人不通过申请,驳回请求)
@Testpublic void testCompleteTask2(){// 审批人String assignee = "lisi";HashMap<String, Object> map = new HashMap<>();// 完成任务时同时指定审核为驳回map.put("audit", false);// 根据变量条件完成对应任务ActivitiUtil.completeTaskWithVariables(assignee, map);}
执行结果:
Logged in as: lisi
TaskImpl{id=’ba78a61b-d8f8-11eb-bb2a-04d3b0ccfa07’, owner=’null’, assignee=’lisi’, name=’审核’, description=’null’, createdDate=Wed Jun 30 00:40:35 CST 2021, claimedDate=null, dueDate=null, priority=50, processDefinitionId=’bohui:1:e2f71a3c-d8bf-11eb-9c08-04d3b0ccfa07’, processInstanceId=’1bac6242-d8e3-11eb-abf7-04d3b0ccfa07’, parentTaskId=’null’, formKey=’null’, status=ASSIGNED, processDefinitionVersion=null, businessKey=null, taskDefinitionKey=_4}
2021-06-30 00:45:05.008 INFO 1940 —- [ main] c.z.a.utils.ActivitiUtil : lisi完成任务
数据表出现的变化
2.2.5 进入审批阶段(申请人重新申请请求)
@Testpublic void testCompleteTask3(){// 申请人String assignee = "zhangsan";// 重新提交任务ActivitiUtil.completeTask(assignee);}
/*** 完成指派人所有任务** @param assignee 指派人*/public static void completeTask(String assignee) {// 获取默认前十条任务Page<org.activiti.api.task.model.Task> tasks = getTaskList(assignee, 0, 10);// 任务总数大于零的场合if (tasks.getTotalItems() > 0) {// 有任务时,完成任务for (org.activiti.api.task.model.Task task : tasks.getContent()) {System.out.println(task);// 完成任务activitiUtil.taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());logger.info(assignee + "完成任务");}}}
2.2.6 进入审批阶段(审批通过)
@Testpublic void testCompleteTask4(){// 审批人String assignee = "lisi";HashMap<String, Object> map = new HashMap<>();// 完成任务时同时指定审核为通过map.put("audit", true);// 根据变量条件完成对应任务ActivitiUtil.completeTaskWithVariables(assignee, map);}
执行结果:
Logged in as: lisi
TaskImpl{id=’d0cddac7-d8f9-11eb-8c91-04d3b0ccfa07’, owner=’null’, assignee=’lisi’, name=’审核’, description=’null’, createdDate=Wed Jun 30 00:48:22 CST 2021, claimedDate=null, dueDate=null, priority=50, processDefinitionId=’bohui:1:e2f71a3c-d8bf-11eb-9c08-04d3b0ccfa07’, processInstanceId=’1bac6242-d8e3-11eb-abf7-04d3b0ccfa07’, parentTaskId=’null’, formKey=’null’, status=ASSIGNED, processDefinitionVersion=null, businessKey=null, taskDefinitionKey=_4}
2021-06-30 00:48:44.667 INFO 9616 —- [ main] c.z.a.utils.ActivitiUtil : lisi完成任务
数据表出现的变化




