目錄
(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 我後面將使用這個參數。
(7)審覈這個請假流程
代碼:
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
這個時候我們可以驗證一下當前這個流程是否 已經執行完,讓我們再執行一下流程執行狀態查詢。
(8)查詢當前請假流程狀態
代碼:
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之在線設計器