java工作流:SpringBoot整合Activiti工作流(附源码)

 2021-06-30 2:27    77  

作者java工作流:yawn-silence

java工作流:SpringBoot整合Activiti工作流(附源码)

my.oschina.net/silenceyawen/blog/1609603

java工作流:SpringBoot整合Activiti工作流(附源码)

依赖:新建springBoot项目时勾选activitijava工作流,或者在已建立的springBoot项目添加以下依赖:

<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version></dependency>配置java工作流:数据源和activiti配置:

 server: port: 8081spring: datasource: url: jdbc:mysql://localhost:3306/act5?useSSL=true driver-class-name: com.mysql.jdbc.Driver username: root password: root # activiti default configuration activiti: database-schema-update: true check-process-definitions: true process-definition-location-prefix: classpath:/processes/# process-definition-location-suffixes:# - **.bpmn# - **.bpmn20.xml history-level: full在activiti的默认配置中,process-definition-location-prefix 是指定activiti流程描述文件的前缀(即路径),启动时,activiti就会去寻找此路径下的流程描述文件,并且自动部署;suffix 是一个String数组,表示描述文件的默认后缀名,默认以上两种。

springMVC配置:

package com.yawn.config;import org.springframework.context.annotation.Configuration;import org.springframework.format.FormatterRegistry;import org.springframework.;import org.springframework.web.servlet.config.annotation.*;/** * Created by yawn on 2017/8/5. */@EnableWebMvc@Configurationpublic class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/templates/"); super.addResourceHandlers(registry); } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/index"); registry.addViewController("/user"); registry.addRedirectViewController("/","/templates/login.html");// registry.addStatusController("/403", ); super.addViewControllers(registry); }}这里配置静态资源和直接访问的页面:在本示例项目中,添加了thymeleaf依赖解析视图,主要采用异步方式获取数据,通过angularJS进行前端数据的处理和展示。

使用activiti:配置了数据源和activiti后,启动项目,activiti 的各个服务组件就已经被加入到spring容器中了,所以就可以直接注入使用了。如果在未自动配置的spring环境中,可以使用通过指定bean的init-method来配置activiti的服务组件。

案例:以以下请假流程为例:

1. 开始流程并“申请请假”(员工)

private static final String PROCESS_DEFINE_KEY = "vacationProcess"; public Object startVac(String userName, Vacation vac) { identityService.setAuthenticatedUserId(userName); // 开始流程 ProcessInstance vacationInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINE_KEY); // 查询当前任务 Task currentTask = taskService.createTaskQuery().processInstanceId(vacationInstance.getId()).singleResult(); // 申明任务 taskService.claim(currentTask.getId(), userName); Map<String, Object> vars = new HashMap<>(4); vars.put("applyUser", userName); vars.put("days", vac.getDays()); vars.put("reason", vac.getReason()); // 完成任务 taskService.complete(currentTask.getId(), vars); return true; }在此方法中,Vaction 是申请时的具体信息,在完成“申请请假”任务时,可以将这些信息设置成参数。

2. 审批请假(老板)

(1)查询需要自己审批的请假

public Object myAudit(String userName) { List<Task> taskList = taskService.createTaskQuery().taskCandidateUser(userName) .orderByTaskCreateTime().desc().list();// / 多此一举 taskList中包含了以下内容(用户的任务中包含了所在用户组的任务)// Group group = identityService.createGroupQuery().groupMember(userName).singleResult();// List<Task> list = taskService.createTaskQuery().taskCandidateGroup(group.getId()).list();// taskList.addAll(list); List<VacTask> vacTaskList = new ArrayList<>(); for (Task task : taskList) { VacTask vacTask = new VacTask(); vacTask.setId(task.getId()); vacTask.setName(task.getName()); vacTask.setCreateTime(task.getCreateTime()); String instanceId = task.getProcessInstanceId(); ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult(); Vacation vac = getVac(instance); vacTask.setVac(vac); vacTaskList.add(vacTask); } return vacTaskList; } private Vacation getVac(ProcessInstance instance) { Integer days = runtimeService.getVariable(instance.getId(), "days", Integer.class); String reason = runtimeService.getVariable(instance.getId(), "reason", String.class); Vacation vac = new Vacation(); vac.setApplyUser(instance.getStartUserId()); vac.setDays(days); vac.setReason(reason); Date startTime = instance.getStartTime(); // activiti 6 才有 vac.setApplyTime(startTime); vac.setApplyStatus(instance.isEnded() ? "申请结束" : "等待审批"); return vac; }

package com.yawn.entity;import java.util.Date;/** * @author Created by yawn on 2018-01-09 14:31 */public class VacTask { private String id; private String name; private Vacation vac; private Date createTime; // getter setter ...}老板查询自己当前需要审批的任务,并且将任务和参数设置到一个VacTask对象,用于页面的展示。

(2)审批请假

public Object passAudit(String userName, VacTask vacTask) { String taskId = vacTask.getId(); String result = vacTask.getVac().getResult(); Map<String, Object> vars = new HashMap<>(); vars.put("result", result); vars.put("auditor", userName); vars.put("auditTime", new Date()); taskService.claim(taskId, userName); taskService.complete(taskId, vars); return true; }同理,result是审批的结果,也是在完成审批任务时需要传入的参数;taskId是刚才老板查询到的当前需要自己完成的审批任务ID。(如果流程在这里设置分支,可以通过判断result的值来跳转到不同的任务)

3. 查询记录

由于已完成的请假在数据库runtime表中查不到(runtime表只保存正在进行的流程示例信息),所以需要在history表中查询。

(1) 查询请假记录

public Object myVacRecord(String userName) { List<HistoricProcessInstance> hisProInstance = historyService.createHistoricProcessInstanceQuery() .processDefinitionKey(PROCESS_DEFINE_KEY).startedBy(userName).finished() .orderByProcessInstanceEndTime().desc().list(); List<Vacation> vacList = new ArrayList<>(); for (HistoricProcessInstance hisInstance : hisProInstance) { Vacation vacation = new Vacation(); vacation.setApplyUser(hisInstance.getStartUserId()); vacation.setApplyTime(hisInstance.getStartTime()); vacation.setApplyStatus("申请结束"); List<HistoricVariableInstance> varInstanceList = historyService.createHistoricVariableInstanceQuery() .processInstanceId(hisInstance.getId()).list(); ActivitiUtil.setVars(vacation, varInstanceList); vacList.add(vacation); } return vacList; }请假记录即查出历史流程实例,再查出关联的历史参数,将历史流程实例和历史参数设置到Vcation对象(VO对象)中去,即可返回,用来展示。

package com.yawn.util;import org.activiti.engine.history.HistoricVariableInstance;import java.lang.reflect.Field;import java.util.List;/** * activiti中使用得到的工具方法 * @author Created by yawn on 2018-01-10 16:32 */public class ActivitiUtil { /** * 将历史参数列表设置到实体中去 * @param entity 实体 * @param varInstanceList 历史参数列表 */ public static <T> void setVars(T entity, List<HistoricVariableInstance> varInstanceList) { Class<?> tClass = entity.getClass(); try { for (HistoricVariableInstance varInstance : varInstanceList) { Field field = tClass.getDeclaredField(varInstance.getVariableName()); if (field == null) { continue; } field.setAccessible(true); field.set(entity, varInstance.getValue()); } } catch (Exception e) { e.printStackTrace(); } }}此外,以上是查询历史流程实例和历史参数后,设置VO对象的通用方法:可以根据参数列表中的参数,将与VO对象属性同名的参数设置到VO对象中去。

4. 前端展示和操作

(1)审批列表和审批操作示例

<div ng-controller="myAudit"> <h2 ng-init="myAudit()">待我审核的请假</h2> <table border="0"> <tr> <td>任务名称</td> <td>任务时间</td> <td>申请人</td> <td>申请时间</td> <td>天数</td> <td>事由</td> <td>操作</td> </tr> <tr ng-repeat="vacTask in vacTaskList"> <td>{{vacTask.name}}</td> <td>{{vacTask.createTime | date:'yyyy-MM-dd HH:mm:ss'}}</td> <td>{{vacTask.vac.applyUser}}</td> <td>{{vacTask.vac.applyTime | date:'yyyy-MM-dd HH:mm:ss'}}</td> <td>{{vacTask.vac.days}}</td> <td>{{vacTask.vac.reason}}</td> <td> <button type="button" ng-click="passAudit(vacTask.id, 1)">审核通过</button> <button type="button" ng-click="passAudit(vacTask.id, 0)">审核拒绝</button> </td> </tr> </table> </div>

app.controller("myAudit", function ($scope, $) { $scope.vacTaskList = []; $scope.myAudit = function () { $( "/myAudit" ).then(function (response) { $scope.vacTaskList = response.data; }) }; $scope.passAudit = function (taskId, result) { $( "/passAudit", { "id": taskId, "vac": { "result": result >= 1 ? "审核通过" : "审核拒绝" } } ).then(function (response) { if (response.data === true) { alert("操作成功!"); $window.location.reload(); } else { alert("操作失败!"); } }) }});以上是一个springBoot 与 activiti 6.0 整合的示例项目的部分代码与说明,完整的项目代码在:

://gitee.com/yawensilence/activiti-demo6-springboot

我目前是在职Java开发,如果你现在正在了解Java技术,想要学好Java,渴望成为一名Java开发工程师,在入门学习Java的过程当中缺乏基础的入门视频教程,你可以关注并私信我:01。我这里有一套最新的Java基础JavaSE的精讲视频教程,这套视频教程是我在年初的时候,根据市场技术栈需求录制的,非常的系统完整。

本文标签:源码SpringBoot工作流

原文链接:https://www.xgfox.com/kfbc/86.html

本文版权:如无特别标注,本站文章均为原创。