十分鐘認識Activiti6.0工作流引擎
十分鐘認識Activiti6.0工作流引擎
概述
瞭解Activiti
假如你還不知道Activiti是什麼,那麼工作流引擎對你來說一定也是新的,解決Activiti和工作流知識盲點,所以看到到這裡就對了,還有Android同學會誤以為是“Activity”,工作流引擎Activiti和Android開發的Activity這是兩碼事兒,Activiti是一個開源的自動化業務工作流引擎,具體概念就不碎碎念介紹了,
使用工作流引擎
工作流引擎最常見用於審批流程中,現在一線網際網路公司也開始使用,並有快速推廣的趨勢,複雜繁多的業務流程如果採用if else實現那將是崩潰的,程式碼不可維護,業務流程在程式碼中可讀性很差,所以高人設計了業務流程模型圖示BPMN2.0,我們要做到就是把業務場景抽象為標準流程圖,把流程圖丟到流程引擎中按流程定義約定逐步流轉,很顯然擴充套件性和業務可描述性會好很多,所以工作流引擎主要用於解決複雜的業務,目前經常被提起的中臺系統抽象業務為服務,也涉及大量智慧的業務流程引擎做支撐。
讓工作流引擎執行
我們快速體驗一個流程的執行過程
搭建流程引擎
我們在IDEA環境中使用 Spring Initializr引導我們建立一個標準工程,採用最新穩定版spring boot 2.0.2,Activiti 6.0,通過引入H2記憶體資料庫,方便我們快速啟動程式演示,而不用費心在建立資料庫相關工作,當程式啟動Spring boot會基於自動配置原理給我們隱式的建立一個工作流引擎物件ProcessEngine,並把RuntimeService(控制流程執行時資料流轉)等核心服務註冊到 Spring 容器中,我們只需要 依賴注入使用即可。
繪製流程圖
繪製流程圖建議大家通過Eclipse + Activiti外掛來繪製,如果大家對流程圖元素還不瞭解,可以直接拷貝流程定義檔案執行,這樣方便快速的執行我們的快速程式
部署流程圖
我們程式碼裡面並沒有體現流程部署的過程,也得益於Spring Boot提供的自動部署功能,也是在Spring 容器啟動的過程通過 activiti-spring元件,把Class path對應的/processes目錄的流程檔案自動載入部署,約定大於配置,快速演示程式碼推薦大家把流程圖放到/processes 資源包下面,線上系統則不建議這樣做
啟動流程
啟動流程是通過流程定義檔案Key建立一個流程例項的過程,類似於我們根據類名new出一個物件的原理,一個流程定義檔案可以生成許許多多的流程例項
多使用者協助審批流程
在命令列下體驗流程審批的效果,對Java後端開發來說,更多的傾向於瞭解底層的原理,而對UI效果興趣不高,其實Activiti也跟我們提供了還不錯的activiti-app來更好的體驗流程的流轉。我們這裡在命令列下執行工作流程,可以滿足一下極客青年小小的虛榮心。
開發
建立工程
基於spring Initializr建立一個標準的maven工程,並新增相關依賴 spring boot 2.0.2最新穩定版,Activiti 6最新穩定版
// pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc.activiti</groupId>
<artifactId>activiti-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>activiti-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.0-jre</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Spring Initializr會自動建立程式啟動入口類ActivitiDemoApplication
/src/main/java/com.imooc.activiti.demo.ActivitiDemoApplicationpackage
com.imooc.activiti.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class ActivitiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ActivitiDemoApplication.class, args);
}
}
設計流程定義檔案
https://img4.mukewang.com/5b1fde170001823818100620.jpg
剛開始設計流程定義檔案推薦大家使用 Eclipse+ Activiti外掛的方式, Activiti也提供了基於瀏覽器的web 流程設計器,都可以分別體驗一下,這個流程定義檔案就是普通的xml,大家應該能很容易看明白這個xml檔案
// src/main/resources/processes/second_approve.bpmn
<?xml version="1.0" encoding="UTF-8"?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test" id="m1528728906382" name="">
<process id="second_approve" name="二級審批流程" isExecutable="true" isClosed="false" processType="None">
<startEvent id="startEvent" name="開始"></startEvent>
<userTask id="submitForm" name="填寫審批資訊">
<extensionElements>
<activiti:formProperty id="message" name="申請資訊" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="name" name="申請人姓名" type="string" required="true"></activiti:formProperty>
<activiti:formProperty id="submitTime" name="提交時間" type="date" datePattern="yyyy-MM-dd" required="true"></activiti:formProperty>
<activiti:formProperty id="submitType" name="確認申請" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitForm"></sequenceFlow>
<exclusiveGateway id="decideSubmit" name="提交OR取消"></exclusiveGateway>
<sequenceFlow id="flow2" sourceRef="submitForm" targetRef="decideSubmit"></sequenceFlow>
<userTask id="tl_approve" name="主管審批">
<extensionElements>
<activiti:formProperty id="tlApprove" name="主管審批結果" type="string"></activiti:formProperty>
<activiti:formProperty id="tlMessage" name="主管備註" type="string" required="true"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow3" sourceRef="decideSubmit" targetRef="tl_approve">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "y" || submitType == "Y"}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway id="decideTLApprove" name="主管審批校驗"></exclusiveGateway>
<sequenceFlow id="flow4" sourceRef="tl_approve" targetRef="decideTLApprove"></sequenceFlow>
<endEvent id="endEvent" name="結束"></endEvent>
<endEvent id="endEventCancel" name="取消"></endEvent>
<sequenceFlow id="flow8" sourceRef="decideSubmit" targetRef="endEventCancel">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${submitType == "n" || submitType == "N"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow9" sourceRef="decideTLApprove" targetRef="submitForm">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${tlApprove == "n" || tlApprove == "N"}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_2" sourceRef="decideTLApprove" targetRef="endEvent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${tlApprove == "y" || tlApprove == "Y"}]]></conditionExpression>
</sequenceFlow>
</process>
</definitions>
開發可以根據spring boot自動裝配的流程樣例
流程執行我們使用了CommandLineRunner,這個類的事例會在Spring boot容器啟動載入完成後直接執行
//src/main/java/com.imooc.activiti.demo.AutoConfigurationProcessDemo
@Configuration
@Slf4jpublic class AutoConfigurationProcessDemo {
@Autowired private RuntimeService runtimeService;
@Autowired private TaskService taskService;
@Autowired private FormService formService;
/**
* 命令列執行
*
* @return
*/
@Bean
public CommandLineRunner commandLineRunner() {
return new CommandLineRunner() {
@Override
public void run(String... args) throws Exception {
log.info("啟動我們的程式");
//啟動執行流程
ProcessInstance processInstance = startProcessInstance("second_approve");
//處理流程任務
processTask(processInstance);
log.info("結束我們的程式");
}
};
} /**
* 處理流程任務
*
* @param processInstance
* @throws ParseException
*/
private void processTask(ProcessInstance processInstance) throws ParseException {
Scanner scanner = new Scanner(System.in);
while (processInstance != null && !processInstance.isEnded()) {
List<Task> list = taskService.createTaskQuery().list();
log.info("待處理任務數量 [{}]", list.size());
for (Task task : list) {
log.info("待處理任務 [{}]", task.getName());
Map<String, Object> variables = buildVariablesByScanner(scanner, task);
taskService.complete(task.getId(), variables);
processInstance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(processInstance.getId())
.singleResult();
}
}
scanner.close();
} /**
* 從控制檯獲取變數
*
* @param scanner
* @param task
* @return
* @throws ParseException
*/
private Map<String, Object> buildVariablesByScanner(Scanner scanner, Task task) throws ParseException {
TaskFormData taskFormData = formService.getTaskFormData(task.getId());
List<FormProperty> formProperties = taskFormData.getFormProperties();
return buildVariablesByScanner(scanner, formProperties);
}
public static Map<String, Object> buildVariablesByScanner(Scanner scanner, List<FormProperty> formProperties) throws ParseException {
Map<String, Object> variables = Maps.newHashMap();
for (FormProperty property : formProperties) {
String line = null;
if (StringFormType.class.isInstance(property.getType())) {
log.info("請輸入 {} ?", property.getName());
line = scanner.nextLine();
variables.put(property.getId(), line);
} else if (DateFormType.class.isInstance(property.getType())) {
log.info("請輸入 {} ? 格式 (yyyy-MM-dd)", property.getName());
line = scanner.nextLine();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = dateFormat.parse(line);
variables.put(property.getId(), date);
} else {
log.info("型別暫不支援 {}", property.getType());
}
log.info("您輸入的內容是 [{}]", line);
}
return variables;
} /**
* 獲取流程例項
*
* @param processDefinitionId
* @return
*/
private ProcessInstance startProcessInstance(String processDefinitionId) {
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId); log.info("啟動流程 [{}]", processInstance.getProcessDefinitionKey()); return processInstance;
}
}
命令列執行效果
可以看到我簡單3個檔案就可以讓工作流程式執行起來,為了讓控制檯輸出更清晰直觀,讓控制檯日誌僅僅輸出message日誌資訊,忽略預設格式中日誌級別時間資訊等等
//src/main/resources/application.yml
logging:
pattern:
console: “%m%n”
我們可以直接在控制檯執行 mvn spring-boot:run,當然也可以mvn package打出一個Jar包後,執行獨立jar包
mvn spring-boot:run
// 輸入正常流程審批通過
啟動我們的程式
啟動流程 [second_approve]
待處理任務數量 [1]
待處理任務 [填寫審批資訊]
請輸入 申請資訊 ?
$辭職,世界那麼大,我想去看看
您輸入的內容是 [辭職,世界那麼大,我想去看看]
請輸入 申請人姓名 ?
$Jimmy
您輸入的內容是 [Jimmy]
請輸入 提交時間 ? 格式 (yyyy-MM-dd)
$2018-05-21
您輸入的內容是 [2018-05-21]
請輸入 確認申請 ?
$Y
您輸入的內容是 [Y]
待處理任務數量 [1]
待處理任務 [主管審批]
請輸入 主管審批結果 ?
$Y
您輸入的內容是 [Y]
請輸入 主管備註 ?
$錢包那麼小,勸你別作妖
您輸入的內容是 [錢包那麼小,勸你別作妖]
結束我們的程式
轉載的是下面這位大牛的, 怕這篇文章刪掉,就轉載過來了,如果侵權馬上刪!
作者:JimmyNo1
連結:https://www.imooc.com/article/details/id/35590
相關文章
- 十分鐘輕鬆讓你認識ASP.NET MVC6ASP.NETMVC
- Activiti6.0 spring5 工作流引擎 java SSM流程審批 專案框架SpringJavaSSM框架
- java Activiti6.0 後臺 框架 spring5 SSM 工作流引擎 審批流程Java框架SpringSSM
- Activiti6.0 java專案框架 spring5 SSM 工作流引擎 審批流程Java框架SpringSSM
- 認識搜尋引擎 ElasticsearchElasticsearch
- java工作流引擎 Activiti6.0 websocket 即時聊天發圖片文字 好友群組 SSM原始碼JavaWebSSM原始碼
- 一分鐘認識 GitGit
- 簡單認識MySQL儲存引擎MySql儲存引擎
- GDB十分鐘教程
- 十分鐘看懂AES加密加密
- 十分鐘快速上手NutUIUI
- 十分鐘搞定 GradleGradle
- 十分鐘學會FlaskFlask
- 十分鐘入門 Less
- 十分鐘入門RocketMQMQ
- 十分鐘掌握SQLite操作SQLite
- 三十分鐘拿Git幹活Git
- 三十分鐘 Docker 新手入門Docker
- 十分鐘學會 PythonPython
- Python十分鐘入門Python
- activiti工作流引擎元件元件
- 十分鐘上手前端UI框架Bootstrap前端UI框架boot
- 三十分鐘掌握Webpack效能優化Web優化
- 十分鐘搞懂分散式爬蟲分散式爬蟲
- 爬蟲程式十分鐘入門爬蟲
- 十分鐘 GET 資料分析技巧
- 十分鐘快速入門 PythonPython
- 十分鐘寫個RPC框架RPC框架
- 十分鐘搞懂Lombok使用與原理Lombok
- Android MVP 十分鐘入門!AndroidMVP
- 十分鐘-Nginx入門到上線Nginx
- Docker三十分鐘快速入門(下)Docker
- 十分鐘學習diff和patch
- 十分鐘搞定CSS選擇器CSS
- 工作流引擎:jbpm和activiti
- 三分鐘看懂新一代.Net Core3.1工作流引擎平臺
- 十分鐘學習泊松分佈
- 十分鐘上手chrome效能分析皮膚Chrome