在 Spring Boot 项目中使用 activiti
程序员文章站
2023-11-09 18:20:58
新建springBoot项目时勾选activiti,或者在已建立的springBoot项目添加以下依赖: org.activiti activiti-spring-boot-starter-basic
新建springboot项目时勾选activiti,或者在已建立的springboot项目添加以下依赖:
<dependency> <groupid>org.activiti</groupid> <artifactid>activiti-spring-boot-starter-basic</artifactid> <version>6.0.0</version> </dependency>
数据源和activiti配置:
server: port: 8081 spring: 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.http.httpstatus; import org.springframework.web.servlet.config.annotation.*; /** * created by yawn on 2017/8/5. */ @enablewebmvc @configuration public 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", httpstatus.forbidden); super.addviewcontrollers(registry); } }
这里配置静态资源和直接访问的页面:在本示例项目中,添加了thymeleaf依赖解析视图,主要采用异步方式获取数据,通过angularjs进行前端数据的处理和展示。
配置了数据源和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, $http, $window) { $scope.vactasklist = []; $scope.myaudit = function () { $http.get( "/myaudit" ).then(function (response) { $scope.vactasklist = response.data; }) }; $scope.passaudit = function (taskid, result) { $http.post( "/passaudit", { "id": taskid, "vac": { "result": result >= 1 ? "审核通过" : "审核拒绝" } } ).then(function (response) { if (response.data === true) { alert("操作成功!"); $window.location.reload(); } else { alert("操作失败!"); } }) } });
本人免费整理了java高级资料,涵盖了java、redis、mongodb、mysql、zookeeper、spring cloud、dubbo高并发分布式等教程,一共30g,需要自己领取。
传送门:https://mp.weixin.qq.com/s/igmojff-bbmq6ircgo3mqa
上一篇: 虚拟机桥接模式下将虚拟IP设为静态IP
推荐阅读
-
在 Spring Boot 项目中使用 activiti
-
spring boot devtools在Idea中实现热部署方法
-
asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFactory,DALMsSql'.
-
使用Spring-boot-starter标准改造项目内的RocketMQ客户端组件
-
JSP开发中在spring mvc项目中实现登录账号单浏览器登录
-
详解在Docker容器中运行Spring Boot应用
-
idea创建一个入门Spring Boot项目(controller层)使用Moven代码管理
-
Vue项目部署在Spring Boot出现页面空白问题的解决方案
-
在Spring Boot中使用Docker在测试中进行高级功能测试
-
在eclipse中使用spring,springmvc,mybatis搭建web项目