目录
(1)新建一个SpringBoot项目,引入 Activti5.22.0 的jar 文件,生成23张工作流的表
(3)启动项目,在浏览器上访问Activiti5.22.0 在线设计器的页面
前言:
小编 做的这个项目有部分功能用到了 Activiti工作流,目前对工作流的掌握程度是基本会用,我之前写过一篇 Activiti 入门篇,当前这篇文章是属于Activiti 实战部分,如果你想知道Activiti 工作流是如何使用的话,那就随着小编一起看下去吧!
源码:
所有源码我会放到网盘里面,欢迎大家下载。
链接:https://pan.baidu.com/s/18TentJlrLNflNAcgJDnAtQ
提取码:9q19
步骤:
(1)新建一个SpringBoot项目,引入 Activti5.22.0 的jar 包,生成23张工作流的表
- 1.1 pom 文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>activiti-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activiti-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--Spring data JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- MySQL start -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<!-- spring boot start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- activiti start -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-explorer</artifactId>
<version>5.22.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-simple-workflow</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-css</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.7</version>
</dependency>
<!-- activiit end-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 1.2 引入生成数据库表的文件,
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--配置流程引擎配置对象-->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://192.168.20.81:3306/activiti_demo"/>
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="root" />
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
- 1.3 启动这个项目,就可以生成工作流的表
如下图所示,我还创建一个了activiti_demo 的数据库
新建23张表的时候,会往 act_ge_property 中新增3条数据
(2) 引入Activiti 5.22.0 所需的文件
- 2.1 整个项目路径如下图所示:
static 文件夹下 是activiti5.22.0 的静态资源文件
- 2.2 工作流模型创建的接口
package com.example.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* 工作流前端化的controller(新建)
*
* @Author: tanghh
*/
@RequestMapping("/activiti")
@RestController
public class ActivitiController {
private static Logger logger=LoggerFactory.getLogger(ActivitiController.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private ObjectMapper objectMapper;
@ResponseBody
public String newMode() {
return "spring-boot";
}
/**
* 根据Model部署流程
*/
@PostMapping(value = "deploy/{modelId}")
public void deploy(@PathVariable("modelId") String modelId) {
try {
Model modelData = repositoryService.getModel(modelId);
ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
byte[] bpmnBytes = null;
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
String processName = modelData.getName() + ".bpmn20.xml";
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionResourceName(processName).list();
for (ProcessDefinition definition:list){
//删除原有流程定义,正在使用的流程定义无法删除
repositoryService.deleteDeployment(definition.getDeploymentId());
}
Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes)).deploy();
System.out.println("流程部署id----"+deployment.getId());
} catch (Exception e) {
logger.error("根据模型部署流程失败:modelId={}", modelId, e);
}
}
/**
* 新建模型
* @return
* @throws UnsupportedEncodingException
*/
@GetMapping("/create")
public ModelAndView newModel() throws UnsupportedEncodingException {
// ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// RepositoryService repositoryService = processEngine.getRepositoryService();
// ObjectMapper objectMapper = new ObjectMapper();
//初始化一个空模型
Model model = repositoryService.newModel();
//设置一些默认信息,可以用参数接收
int revision = 1;
String key = "process";
String name = "process";
String description = "新建流程模型";
//ModelEditorSource
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset" , stencilSetNode);
ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
model.setName(name);
model.setKey(key);
model.setMetaInfo(modelNode.toString());
repositoryService.saveModel(model);
String id = model.getId();
repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
return new ModelAndView("redirect:/modeler.html?modelId=" + id);
}
}
(3)启动项目,在浏览器上访问Activiti5.22.0 在线设计器的页面
在浏览器上访问这个路径: http://localhost:8005/activiti/create
(4)画流程图的注意事项
- 4.1 像这种设计器一般情况都是可以拖拽的,如下图我就是鼠标放到开始事件上 ,拖到右边界面上
- 4.2 点击 我标注的那个人头 ,就可以创建像我左边那样的 发起请假流程的框
- 4.3 画流程图的时候 鼠标箭头要对准 这些红点点,不要留有空隙,不然创建流程实例的时候会报错
箭头最好是可以多拖拽一点,不然会报下面这个错。
- 4.4 如何给一个任务一个名字 ,可以在我下图中标注的地方 填写
- 4.5 定义一个审核人
- 4.6 俩个跳转条件(驳回 和同意)
- 4.7 最终画出来的请假流程如下图:
小编画的不咋好看, 你也可以按照你喜欢的来调
- 4.8 点击保存这个流程
点击 图标出来的界面:
- 4.9 需要注意的一个点:
注意: 1 这是流程id 是唯一的 ,后面我们创建流程实例 ,要基于这个流程id 来创建。
- 4.10 创建一个流程添加数据
创建一个模型的时候,会往 act_re_model中添加一条数据,
act_ge_ bytearray 中添加数据
(5)创建一个请假流程
- 5.1 创建一个请假流程实例:
代码:
TestActivitiController 类
@Autowired
private ActivitiService activitiService;
/**
* 1.创建一个流程实例
*/
@GetMapping(value = "/createLeaveFlow")
public void createLeaveFlow() throws IOException {
//1.举个例子,soup_tang 需要请假 ,我在页面上添加请假申请,任务申请人是soup_tang,
// 我选择审核人为汤总,请汤总给我审核这个请假流程。
String checkPeople = "汤总";
activitiService.createLeaveWorkFlow(checkPeople);
}
ActivitiService 类
@Override
public void createLeaveWorkFlow(String checkPeople) throws IOException {
//先判断这个流程文件有没有部署(只需部署一次)
Model modelData = repositoryService.getModel("1");
ObjectNode modelNode = (ObjectNode) new ObjectMapper()
.readTree(repositoryService.getModelEditorSource(modelData.getId()));
byte[] bpmnBytes = null;
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(modelNode);
bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment()
.name(modelData.getName()).addString(processName, new String(bpmnBytes, "UTF-8"))
.deploy();
//获取流程定义
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
//启动流程定义,返回流程实例
Map<String,Object> map = new HashMap<>();
map.put("checkPeople",checkPeople);
ProcessInstance pi = runtimeService.startProcessInstanceById(processDefinition.getId(),map);
System.out.println("流程定义的ID:" + pi.getProcessDefinitionId());
System.out.println("流程实例的ID:" + pi.getId());
}
浏览器上访问 http://localhost:8005/createLeaveFlow
就会往正在运行的表中生成数据
正在运行的参数表
(6)查询正在运行的请假流程
代码:
TestActivitiController
/**
* 3.查询正在运行的实例
*/
@GetMapping(value = "/listLeaveFlow")
public void listLeaveFlow() {
activitiService.queryExcution();
}
ActivitiService
/**
* 查询正在运行的实例
*/
@Override
public void queryExcution() {
//创建正在执行的流程查询对象
List<Execution> executionList = runtimeService.createExecutionQuery()
.list(); //查询出集合
for(Execution execution: executionList){
System.out.println("正在执行的流程对象的id: "+execution.getId());
System.out.println("所属流程实例的id:"+execution.getProcessInstanceId());
System.out.println("正在活动的节点的id: "+execution.getActivityId());
}
}
浏览器上访问:http://localhost:8005/listLeaveFlow
其中比较重要的就是这个流程实例id 2507 我后面将使用这个参数。
(6)审核这个请假流程
代码:
TestActivitiController类
/**
* 2.执行完 第一个方法的创建流程以后,就要执行下面这个审核方法
* @throws IOException
*/
@GetMapping(value = "/assginLeaveFlow")
public void assginLeaveFlow() {
//1.当汤总 登录系统的时候,他需要审核一些 审核人为他的 请假流程,当然了,我们在创建这个请假流程的时候,
//我这个审核人就是可以动态赋值的
//2.这个是流程实例id ,每次创建一个工作流,都会生成,在具体的生产环境中我们需要将这个流程实例id保存起来。(2507 可能需要替换喔 切记。)
String processInstanceId = "2507";
//3.这个是审核人是否同意当前这个流程。(0代表同意 1代表不同意)
int isAcceppt = 0;
//4.这个是当前审核人
String checkPeople = "汤总";
activitiService.assginLeaveWorkFlow(processInstanceId,isAcceppt,checkPeople);
}
ActivitiService类
@Override
public void assginLeaveWorkFlow(String processInstanceId,int isAccept,String checkPeople) {
Map<String,Object> map = new HashMap<>();
//得到当前实例下的task
Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
taskService.addComment(task.getId(), processInstanceId, "审核人是否同意该请假流程");
if(isAccept == 0){
System.out.println("审核人同意了该请求");
map.put("accept","同意");
task.setAssignee(checkPeople);
map.put("checkPeople", checkPeople);
}else{
System.out.println("审核人驳回了该请求");
map.put("accept","驳回");
//审核驳回后
task.setAssignee("soup_tang");
map.put("auditor","soup_tang");
}
task.setDescription("请假的描述信息");
//执行当前这个工作流任务
taskService.saveTask(task);
taskService.complete(task.getId(), map);
}
浏览上访问:http://localhost:8005/assginLeaveFlow
这个时候我们可以验证一下当前这个流程是否 已经执行完,让我们再执行一下流程执行状态查询。
(7)查询当前请假流程状态
代码:
TestActiviController
/**
* 3.查询正在运行的实例
*/
@GetMapping(value = "/getLeaveFlowByProccessInstanceId")
public void getLeaveFlowByProccessInstanceId() {
String proccessInstanceId = "2507";
activitiService.queryProccessInstanceState(proccessInstanceId);
}
ActivitiService
@Override
public void queryProccessInstanceState(String proccessInstanceId) {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(proccessInstanceId).singleResult();
if (processInstance == null) {
System.out.println("当前流程已经完成");
} else {
System.out.println("当前流程实例ID:" + processInstance.getId());
System.out.println("当前流程所处的位置:" + processInstance.getActivityId());
}
}
浏览器上访问:http://localhost:8005/getLeaveFlowByProccessInstanceId
注意事项:
1.我在测试的时候,发现当一个流程执行完以后,对应的 act_ru_task当中的数据也会被清空掉,数据会保存到 hi开头的表中。
2.其中比较重要的就是这个流程实例id 2507 我后面将使用这个参数。
3.我目前使用的是Activiti5.22.0 版本。
4.这篇文章写不下了,下篇文章 我会介绍如何高亮显示一个工作流实例,以及查询历史任务,以及 如何挂起,激活,删除一个流程,敬请期待。
参考文章:
SpringBoot集成Activiti之在线设计器 狂飙的蜗牛_013dpringBoot 集成Activi之在线设计器