转载

在 Spring Boot 项目中使用 activiti

来源 | www.jvm123.com

链接:

www.jvm123.com/2019/08/springboot-activiti/

新建springBoo t项目时勾选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的服务组件。

以以下请假流程为例:

在 Spring Boot 项目中使用 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.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)审批列表和审批操作示例

在 Spring Boot 项目中使用 activiti

< 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("操作失败!");

}

})

}

});

以上是一个springBoot 与 activiti 6.0 整合的示例项目的部分代码与说明,完整的项目代码在:

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

原文请查看作者博客:

http://www.jvm123.com/2019/08/springboot-activiti/

- END -

如果看到这里,说明你喜欢这篇文章,请 转发 、点赞 扫描下方二维码 或者微信搜索「 perfect_iscas 」,添加好友后即可获得 10套程序员全栈课程+1000套PPT和简历模板 向我私聊「 进群 」二字即可进入高质量交流群。

扫描二维码进群↓

在 Spring Boot 项目中使用 activiti

在 Spring Boot 项目中使用 activiti

在看  在 Spring Boot 项目中使用 activiti

原文  http://mp.weixin.qq.com/s?__biz=MzU4NjIxODMyOQ==&mid=2247487497&idx=6&sn=84826548ca31948e3de812eced495951
正文到此结束
Loading...