在 Spring Boot 项目中使用 activiti
新建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
在 Spring Boot 项目中使用 activiti的更多相关文章
- 你真的理解 Spring Boot 项目中的 parent 吗?
前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent> <groupId ...
- Spring Boot项目中使用Swagger2
Swagger2是一款restful接口文档在线生成和在线接口调试工具,Swagger2在Swagger1.x版本的基础上做了些改进,下面是在一个Spring Boot项目中引入Swagger2的简要 ...
- 在Spring Boot项目中使用Spock框架
转载:https://www.jianshu.com/p/f1e354d382cd Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring B ...
- Spring Boot2 系列教程(三)理解 Spring Boot 项目中的 parent
前面和大伙聊了 Spring Boot 项目的三种创建方式,这三种创建方式,无论是哪一种,创建成功后,pom.xml 坐标文件中都有如下一段引用: <parent> <groupId ...
- Spring Boot项目中使用Mockito
本文首发于个人网站:Spring Boot项目中使用Mockito Spring Boot可以和大部分流行的测试框架协同工作:通过Spring JUnit创建单元测试:生成测试数据初始化数据库用于测试 ...
- 在Spring Boot项目中使用Spock测试框架
本文首发于个人网站:在Spring Boot项目中使用Spock测试框架 Spock框架是基于Groovy语言的测试框架,Groovy与Java具备良好的互操作性,因此可以在Spring Boot项目 ...
- Spring Boot项目中如何定制拦截器
本文首发于个人网站:Spring Boot项目中如何定制拦截器 Servlet 过滤器属于Servlet API,和Spring关系不大.除了使用过滤器包装web请求,Spring MVC还提供Han ...
- Spring Boot项目中如何定制PropertyEditors
本文首发于个人网站:Spring Boot项目中如何定制PropertyEditors 在Spring Boot: 定制HTTP消息转换器一文中我们学习了如何配置消息转换器用于HTTP请求和响应数据, ...
- Spring Boot项目中如何定制servlet-filters
本文首发于个人网站:Spring Boot项目中如何定制servlet-filters 在实际的web应用程序中,经常需要在请求(request)外面增加包装用于:记录调用日志.排除有XSS威胁的字符 ...
随机推荐
- nginx一:安装和基本应用
Nginx: 目录 Nginx:... 1 NGINX简介和安装... 1 网站... 1 全称... 2 二次开发版... 2 Nginx的特性... 2 基本功能... 2 web服务相关的功能. ...
- cookies与session简介
一.session和cookie 简单来讲cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于采用服务器端保持状态的方案在客户端 ...
- Django简介以及MVC模式
一.简介 Django,是当前Python世界里最负盛名且成熟的网络框架.最初用来制作在线新闻的Web站点. Django是一个基于python的web重量级框架 重指的是为发开者考虑的多 采用了MV ...
- GO 单例模式
wiki百科: 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为.比 ...
- 移动端touch滑动事件监听
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 如何将本地项目推送到码云仓库或者GitHub仓库
将本地项目推送到码云仓库. 前提: git 和码云 1.在码云上先创建一个仓库. 2.在要被上传的项目的目录右键, 选择 Git Bash Here. 3.在窗口输入命令: git init 这时 ...
- Jest测试框架入门
近年来,随着前端工程化的发展,前端发生了翻天覆地的变化.jQuery已经慢慢淡出了我们的视野,React.Vue和anglur三驾马车急速驶来.从此,前端进入了数据驱动的时代,也有了清晰的模块化开发的 ...
- Spring Cloud Hoxton正式发布,Spring Boot 2.2 不再孤单
距离Spring Boot 2.2.0的发布已经有一个半月左右时间,由于与之匹配的Spring Cloud版本一直没有Release,所以在这期间碰到不少读者咨询的问题都是由于Spring Boot和 ...
- bash中$符号的一般用法
$一般用于获取变量的内容(字符串或数字等),用以构成命令version=$(uname -r).构成字符串echo "my name is $myname".进行算术运算等tota ...
- nbuoj2780 旅游问题
题目:http://www.nbuoj.com/v8.83/Problems/Problem.php?pid=2780 题意:莫得题意 原以为是道究极蠢的贪心,但是被一发wa打脸,给上wa点,还是太年 ...