這裏實驗工做流開發:使用STS做爲IDE,使用Activiti做爲工做流框架。
javascript
安裝和使用STS的方法,此處再也不贅述。html
一、自動建立工做流表前端
建立一個Springboot項目,java
修改POM文件:mysql
<?xml version="1.0" encoding="UTF-8"?>git
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"angularjs
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">github
<modelVersion>4.0.0</modelVersion>web
<parent>spring
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.edison</groupId>
<artifactId>activiti-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activiti-test</name>
<description>Demo project for activiti</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- activiti -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<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>
修改入口類:
package com.edison.demo;
import org.activiti.spring.boot.SecurityAutoConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {"com.edison.demo"})
@MapperScan(basePackages = {"com.edison.demo"})
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class ActivitiTestApplication {
public static void main(String[] args) {
SpringApplication.run(ActivitiTestApplication.class, args);
}
}
修改application.properties:
server.port=8080
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db_activiti?serverTimezone=Asia/Chongqing&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=radar
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.edison.model
spring.activiti.check-process-definitions=false
直接在STS中啓動微服務,
該服務會建立28張表,
以下:
表分類 |
表名稱 |
表含義 |
事件 |
act_evt_log |
事件處理日誌表 |
通常數據 |
act_ge_bytearray |
通用的流程定義和流程資源 |
act_ge_property |
系統相關屬性 |
|
流程歷史記錄 |
act_hi_actinst |
歷史的流程實例 |
act_hi_attachment |
歷史的流程附件 |
|
act_hi_comment |
歷史的說明性信息 |
|
act_hi_detail |
歷史的流程運行中的細節信息 |
|
act_hi_identitylink |
歷史的流程運行過程當中用戶關係 |
|
act_hi_procinst |
歷史的流程實例 |
|
act_hi_taskinst |
歷史的任務實例 |
|
act_hi_varinst |
歷史的流程運行中的變量信息 |
|
用戶用戶組表 |
act_id_group |
身份信息-組信息 |
act_id_info |
身份信息-組信息 |
|
act_id_membership |
身份信息-用戶和組關係的中間表 |
|
act_id_user |
身份信息-用戶信息 |
|
act_procdef_info |
死信任務 |
|
流程定義表 |
act_re_deployment |
部署單元信息 |
act_re_model |
模型信息 |
|
act_re_procdef |
已部署的流程定義 |
|
運行實例表 |
act_ru_deadletter_job |
執行失敗任務表 |
act_ru_event_subscr |
運行時事件 |
|
act_ru_execution |
運行時流程執行實例 |
|
act_ru_identitylink |
運行時用戶關係信息 |
|
act_ru_job |
運行時做業 |
|
act_ru_suspended_job |
運行時暫停任務 |
|
act_ru_task |
運行時任務 |
|
act_ru_timer_job |
運行時定時任務 |
|
act_ru_variable |
運行時變量表 |
可能遇到的錯誤:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Table 'db_activiti.act_ge_property' doesn't exist
### The error may exist in org/activiti/db/mapping/entity/Property.xml
解決方法:極可能在另一個數據庫中已經存在act_ge_property,把另一個庫中act相關的表刪除後便可。
二、ACTIVITI工做流術語
(1) 業務流程
一個ProcessDefinition表明的業務流程。它用於定義流程中不一樣步驟的結構和行爲。
(2) 流程定義
部署流程定義意味着將流程定義加載到Activiti數據庫中。
(3) BPMN 2.0標準
流程定義主要由BPMN 2.0標準定義,也可使用Java代碼定義它們,定義的全部術語也可用做Java類。
(4) 流程process
一旦咱們開始運行流程定義,就能夠稱爲一個流程process。
(5) processInstance
processInstance是ProcessDefinition一個執行實例。
(6) StartEvent
一個StartEvent與每個業務流程有關,它表示該流程的切入點,一樣,有一個EndEvent表示流程的結束。咱們能夠定義這些事件的條件。
(7) 任務
開始和結束之間的全部步驟(或元素)稱爲任務,任務能夠是各類類型的。最經常使用的任務是UserTasks和ServiceTasks。
(8)服務
RepositoryService:幫助咱們實現流程定義的部署。此服務會處理與流程定義相關的靜態數據。
RuntimeService:管理 ProcessInstances(當前正在運行的流程)以及流程變量
TaskService:會跟蹤 UserTasks,須要由用戶手動執行的任務是Activiti API的核心。咱們可使用此服務建立任務,聲明並完成任務,分配任務的受讓人等。
FormService:是一項可選服務,它用於定義中開始表單和任務表單。
IdentityService:管理用戶和組。
HistoryService:會跟蹤Activiti Engine的歷史記錄。咱們還能夠設置不一樣的歷史級別。
ManagementService:與元數據相關,在建立應用程序時一般不須要。
DynamicBpmnService:幫助咱們在不從新部署的狀況下更改流程中的任何內容。
三、增長設計器插件
在線安裝:在STS中Help -> Install New SoftWare-> Add:
Name: Activiti Designer
Location: http://activiti.org/designer/update/
在線安裝每每會失敗。
離線安裝:安裝失敗就使用離線下載,官方提示連接:
https://github.com/Activiti/Activiti-Designer/releases
下載地址:
https://www.activiti.org/designer/archived/activiti-designer-5.18.0.zip
可是這個文件不完整,還差文件,缺失的jar包在錯誤提示裏面有,能夠從mvnreprository.com中找到。
如下連接是已經測試經過的完整文件:
https://gitee.com/radarfyh/spring-cloud-test/tree/spring-cloud-test/activiti-test
以下圖,activiti-designer-5.18.0.zip文件是官網下載的,plugins.zip裏面是缺失的文件,解壓後放入前一個zip中。
而後在STS中Help -> Install New SoftWare-> Add:
由此能夠成功安裝。
安裝成功後,在new建項目的other目錄下能夠找到:
到preferences中修改設置:
4、入門項目
(1)新建Springboot項目,POM文件引入spring-boot-starter-web、angularjs、activiti-spring-boot-starter-basic、mysql-connector-java,以下:
<?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.1.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.edison</groupId>
<artifactId>activiti-test6</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>activiti-test6</name>
<description>測試初始工做流項目</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>angularjs</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</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>
(2)入口類修改成:
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
@RestController
public class ActivitiTest6Application {
public static void main(String[] args) {
SpringApplication.run(ActivitiTest6Application.class, args);
}
@GetMapping("/test")
public User sayHello(){
System.out.println("----採用angularjs----");
User user = new User();
user.setName("admin");
user.setPassword("123456");
return user;
}
}
(3)新增用戶類:
public class User {
String id;
String name;
String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
(4)新增任務描述類:
public class TaskRepresentation {
private String id;
private String name;
public TaskRepresentation(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
(5)新增服務類:
@Service
public class ActivitiService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
public String start() {
ProcessInstance instance = runtimeService.startProcessInstanceByKey("myProcess");
return instance.getId();
}
public List<Task> getTask(String uid) {
List<Task> tasks = taskService.createTaskQuery().taskAssignee(uid).list();
return tasks;
}
}
(6)新增控制類:
@RestController
@RequestMapping(value = "activiti")
public class ActivitiController {
@Autowired
private ActivitiService service;
@RequestMapping(value = "start", method = RequestMethod.GET)
public String start() {
return service.start();
}
@RequestMapping(value = "task", method = RequestMethod.GET)
public List<TaskRepresentation> getTask(@RequestParam(value = "uid") String uid) {
List<Task> tasks = service.getTask(uid);
List<TaskRepresentation> dtos = new ArrayList<>();
for (Task task : tasks) {
dtos.add(new TaskRepresentation(task.getId(), task.getName()));
}
return dtos;
}
}
(7)新增審批流程(activiti diagram),以下:
其中流程id爲myProcess,審批任務的審覈者Assignee爲admin。
(8)新增前端頁面index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>流程測試首頁</title>
</head>
<!--<script type="text/javascript" src="js/angular.js"></script>-->
<script type="text/javascript"
src="webjars/angularjs/1.7.2/angular.min.js"></script>
<script type="text/javascript" src="controller/userController.js"></script>
<body>
<h1>測試activiti</h1>
<div ng-app="myApp" >
<div ng-controller="userController" ng-init="queryTasks()">
<h2>待我審覈的任務</h2>
<table border="2">
<tr>
<td>id</td>
<td>名稱</td>
</tr>
<tr ng-repeat="vacTask in vacTaskList">
<td>{{vacTask.id}}</td>
<td>{{vacTask.name}}</td>
</tr>
</table>
<h4>{{title}}{{number}}</h4>
</div>
</div>
</body>
</html>
(9)新增angularjs的控制器userController.js:
var app=angular.module("myApp",[]);
app.controller("userController",function ($scope,$http) {
$scope.vacTaskList = [];
$scope.queryTasks = function () {
$http.get(
"/activiti/task?uid=admin"
).then(function (response) {
$scope.vacTaskList = response.data;
$scope.title = "任務數量爲:";
$scope.number=$scope.vacTaskList.length;
})
};
})
(10)新增配置文件application.yml,以下:
server:
port: 8082
spring:
datasource:
url: jdbc:mysql://localhost:3306/act5?serverTimezone=Asia/Chongqing&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: radar
# 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
(11)使用chrome測試:
(12)可能遇到的錯誤
錯誤:Could not update Activiti database schema: unknown version from database: '6.0.0.4'
解決辦法:刪除之前的activiti表:
錯誤:Cannot instantiate interface org.springframework.context.ApplicationContextInitializer
詳細提示:
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.0.4.RELEASE:run (default-cli) on project activiti-test1: An exception occurred while running. null: InvocationTargetException: Cannot instantiate interface org.springframework.context.ApplicationContextInitializer : org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer: org.springframework.core.KotlinDetector.isKotlinReflectPresent()Z -> [Help 1]
解決辦法:編譯經過後,這是使用mvn spring-boot:run出現的錯誤
錯誤:Description Resource Path Location Type
Failed to read artifact descriptor for com.fasterxml.jackson.core:jackson-core:jar:2.9.6
解決辦法:這是POM提示的錯誤,在本地倉庫中找到_remote.repositories,把其中兩個的遠程倉庫指定爲私服alfresco,或者其餘服,例如私服nexus,中央服central
若是項目太多,刪除他們,只剩一個,這樣能夠解決各個項目之間的影響,猜想是STS的bug。STS的版本爲:4.5.1.RELEASE
錯誤:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
......
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
解決方案:
在註解@SpringBootApplication後面加入exclude,以下:
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
注意import 的包不要錯了,應該引入:
import org.activiti.spring.boot.SecurityAutoConfiguration;