記錄一下工作流的在Springboot中的使用,,順便寫個demo,概念,什么東西的我就不解釋了,如有問題歡迎各位大佬指導(dǎo)一下。
1.創(chuàng)建springboot項目后導(dǎo)入依賴
1
2
3
4
5
|
< dependency > < groupId >org.activiti</ groupId > < artifactId >activiti-spring-boot-starter-basic</ artifactId > < version >6.0.0</ version > </ dependency > |
添加配置之后再springboot啟動類后面加上一行代碼否則啟動時會報錯
1
|
@SpringBootApplication (exclude = SecurityAutoConfiguration. class ) |
添加數(shù)據(jù)源以及activiti的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
|
spring: activiti: database-schema-update: drop‐create //默認(rèn)為false,activiti在啟動的時候會對比數(shù)據(jù)庫中的表中保存的版本,如果不一樣會拋出異常 // true activiti會對數(shù)據(jù)庫中的表進行更新操作,如果表不存在,則自動創(chuàng)建 // create_drop 在activiti啟動的時候創(chuàng)建表,關(guān)閉時刪除表,必須手動關(guān)閉 // drop-create 在啟動的時候先刪除表后再創(chuàng)建新的表 check-process-definitions: false datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC username: root password: root |
2.初始化activiti表
這里一共有3種方式去創(chuàng)建
第一種
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@Test public void initTables() { //創(chuàng)建數(shù)據(jù)源 // DriverManagerDataSource dataSource=new DriverManagerDataSource(); // dataSource.setDriverClassName("com.mysql.jdbc.Driver"); // dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test"); // dataSource.setUsername("root"); // dataSource.setPassword("root"); // 創(chuàng)建流程引擎的配置 ProcessEngineConfiguration configuration = ProcessEngineConfiguration .createStandaloneProcessEngineConfiguration(); configuration.setJdbcDriver( "com.mysql.cj.jdbc.Driver" ); configuration.setJdbcUrl( "jdbc:mysql://localhost:3306/test?useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC" ); configuration.setJdbcUsername( "root" ); configuration.setJdbcPassword( "root" ); // configuration.setDataSource(dataSource); /** * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE 如果數(shù)據(jù)庫里面沒有activit的表,也不會創(chuàng)建 * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP 創(chuàng)建表,使用完之后刪除 * ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE 如果數(shù)據(jù)庫里面沒有表,就創(chuàng)建 * * dorp-create 代表如果數(shù)據(jù)庫里面有表,那么先刪除再創(chuàng)建 * */ //配置表的初始化的方式 configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); //得到流程引擎 ProcessEngine processEngine=configuration.buildProcessEngine(); System.out.println(processEngine); } |
第二種配置activiti.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<? xml version = "1.0" encoding = "UTF-8" ?> < 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:aop = "http://www.springframework.org/schema/aop" 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.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> < bean id = "processEngineConfiguration" class = "org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration" > < property name = "jdbcDriver" value = "com.mysql.cj.jdbc.Driver" ></ property > < property name = "jdbcUrl" value = "jdbc:mysql://localhost:3306/test?useUnicode=true%26nullCatalogMeansCurrent=true%26characterEncoding=utf8%26useSSL=false%26serverTimezone=UTC" ></ property > < property name = "jdbcUsername" value = "root" ></ property > < property name = "jdbcPassword" value = "root" ></ property > <!-- flase: 默認(rèn)值。activiti在啟動時,會對比數(shù)據(jù)庫表中保存的版本,如果沒有表或者版本不匹配,將拋出異常。 true: activiti會對數(shù)據(jù)庫中所有表進行更新操作。如果表不存在,則自動創(chuàng)建。 create_drop: 在activiti啟動時創(chuàng)建表,在關(guān)閉時刪除表(必須手動關(guān)閉引擎,才能刪除表)。 drop-create: 在activiti啟動時刪除原來的舊表,然后在創(chuàng)建新表(不需要手動關(guān)閉引擎)。 --> < property name = "databaseSchemaUpdate" value = "drop-create" ></ property > </ bean > </ beans > |
然后寫一個測試類
1
2
3
4
5
6
7
8
9
|
@Test public void intiTables2() { ProcessEngineConfiguration configuration = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource( "activiti.cfg.xml" ); // 得到流程引擎 ProcessEngine processEngine = configuration.buildProcessEngine(); System.out.println(processEngine); } |
第三種方法
1
2
3
4
5
6
|
@Test public void intiTables3() { //必須創(chuàng)建activiti.cfg.xml 并配置好數(shù)據(jù)庫的信息 ProcessEngine processEngine= ProcessEngines.getDefaultProcessEngine(); System.out.println(processEngine); } |
3.打開數(shù)據(jù)庫查看
我們打開數(shù)據(jù)庫查看數(shù)據(jù)庫,會發(fā)現(xiàn)activiti已自動幫我們創(chuàng)建了28張表(有的好像也只有24張表,有興趣的可以研究一下)
這里為大家解釋一下各張表的含義:Activiti的后臺是有數(shù)據(jù)庫的支持,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標(biāo)識。
ACT_RE_*: 'RE'表示repository。 這個前綴的表包含了流程定義和流程靜態(tài)資源 (圖片,規(guī)則,等等)。
ACT_RU_*: 'RU'表示runtime。 這些運行時的表,包含流程實例,任務(wù),變量,異步任務(wù),等運行中的數(shù)據(jù)。 Activiti只在流程實例執(zhí)行過程中保存這些數(shù)據(jù), 在流程結(jié)束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 這些表包含身份信息,比如用戶,組等等。
ACT_HI_*: 'HI'表示history。 這些表包含歷史數(shù)據(jù),比如歷史流程實例, 變量,任務(wù)等等。
ACT_GE_*: 通用數(shù)據(jù), 用于不同場景下,如存放資源文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#RepositoryService Select * from act_ge_bytearray; 二進制文件夾表 Select * from act_re_deployment; 流程部署表 Select * from act_re_procdef; 流程定義表 Select * from act_ge_property; 屬性數(shù)據(jù)表存儲整個流程引擎級別的數(shù)據(jù),初始化表結(jié)構(gòu)時,會默認(rèn)插入三條記錄 #RuntimeService TaskService 運行時數(shù)據(jù)庫表 Select * from act_ru_excution; 流程啟動一次只要沒有執(zhí)行完就會有一條數(shù)據(jù) Select * from act_ru_task; 可能有多條數(shù)據(jù) Select * from act_ru_variable; 記錄流程運行時的流程變量 Select * from act_ru_identitylink; 存放流程辦理人的信息 #HistoryService 歷史數(shù)據(jù)庫表 Select * from act_hi_procinst; 歷史流程實例 Select * from act_hi_taskinst; 歷史任務(wù)實例 Select * from act_hi_actinst; 歷史節(jié)點表 Select * from act_hi_attachment; 歷史附件表 Select * from act_hicomment; 歷史意見表 Select * from act_hi_identitylink; 歷史流程人員表 Select * from act_hi_detail; 歷史詳情表提供歷史變量查詢 Select * from act_hi_procinst; 歷史流程實例表 Select * from act_hi_taskinst; 歷史任務(wù)實例表 Select * from act_hi_varinst; 歷史變量表 #IdentityService 這四張表盡量使用自己的一套,難以滿足需求 Select * from act_id_group; 用戶組信息表 Select * from act_id_info; 用戶拓展信息表 Select * from act_id_menbership; 用戶與用戶組對應(yīng)表 Select * from act_id_user; 用戶信息表 |
4.接下來開始畫請假流程圖(需要先安裝插件),新建一個bpm文件開始編輯
Assignee相當(dāng)于辦理人的意思 我這里是zhang 提出申請,主管yuan 審核。
5.部署流程流程
1
2
3
4
5
6
7
8
9
10
|
// 得到流程引擎 private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); @Test public void deployProcess01() { // 得到流程部署的service RepositoryService repositoryService = this .processEngine.getRepositoryService(); Deployment deploy = repositoryService.createDeployment().name( "請假流程" ).addClasspathResource( "activitiTest.bpmn" ).deploy(); System.out.println( "部署成功:流程部署ID:" + deploy.getId()); } |
6.啟動流程(這里的key與第五部第一張途中對應(yīng))
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this .processEngine.getRuntimeService(); // String processDefinitionId="HelloWorld:1:4"; // runtimeService.startProcessInstanceById(processDefinitionId); String processDefinitionKey= "mytest" ; runtimeService.startProcessInstanceByKey(processDefinitionKey); System.out.println( "流程啟動成功" ); } |
7.根據(jù)用戶查詢?nèi)蝿?wù)(這里使用流程圖中的assignee字段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Test public void queryTask() { TaskService taskService = this .processEngine.getTaskService(); String assignee= "chen" ; List<Task> list = taskService.createTaskQuery().taskAssignee(assignee).list(); if ( null !=list&&list.size()> 0 ) { for (Task task : list) { System.out.println( "任務(wù)ID:" +task.getId()); System.out.println( "流程實例ID:" +task.getProcessInstanceId()); System.out.println( "執(zhí)行實例ID:" +task.getExecutionId()); System.out.println( "流程定義ID:" +task.getProcessDefinitionId()); System.out.println( "任務(wù)名稱:" +task.getName()); System.out.println( "任務(wù)辦理人:" +task.getAssignee()); System.out.println( "################################" ); } } } |
8.辦理任務(wù)(配合步驟8查詢出taskid然后進行辦理任務(wù))
1
2
3
4
5
6
7
|
@Test public void completeTask() { TaskService taskService = this .processEngine.getTaskService(); String taskId= "5005" ; //步驟8中查詢出來的taskId taskService.complete(taskId); System.out.println( "任務(wù)完成" ); } |
重復(fù)7、8兩個步驟,自此一個完整的請假流程就完成了。
那么肯定會有人問了,如果我想查看一我們流程定義的信息,流程圖,刪除流程定義等怎么辦呢,話不多說直接上代碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
|
package com.example; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngines; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.junit.jupiter.api.Test; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipInputStream; public class TestProcessProdef { // 得到流程引擎 private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); /** * 部署流程使用classpath */ @Test public void deployProcess01() { // 得到流程部署的service RepositoryService repositoryService = this .processEngine.getRepositoryService(); Deployment deploy = repositoryService.createDeployment().name( "請假流程2" ).addClasspathResource( "activiti.bpmn" ).deploy(); System.out.println( "部署成功:流程部署ID:" + deploy.getId()); } /** * 查詢流程部署信息 act_re_deployment */ @Test public void queryProcessDeploy() { RepositoryService repositoryService = this .processEngine.getRepositoryService(); // 創(chuàng)建部署信息的查詢 String deploymentId = "1" ; // Deployment deploy = repositoryService.createDeploymentQuery() List<Deployment> list = repositoryService.createDeploymentQuery() // 條件 // .deploymentId(deploymentId) //根據(jù)部署ID去查詢 // .deploymentName(name)//根據(jù)部署名稱去查詢 // .deploymentTenantId(tenantId)//根據(jù)tenantId去查詢 // .deploymentNameLike(nameLike)//根據(jù)部署名稱模糊查詢 // .deploymentTenantIdLike(tenantIdLike)//根據(jù)tenantId模糊查詢 // 排序 // .orderByDeploymentId().asc() //根據(jù)部署ID升序 // .orderByDeploymenTime().desc() //根據(jù)部署時間降序 // .orderByDeploymentName()//根據(jù)部署名稱升序 // 結(jié)果集 .list(); // 查詢返回list集合 // .listPage(firstResult, maxResults) 分頁查詢返回list集合 // .singleResult(); //返回單個對象 // .count(); /* * System.out.println("部署ID:"+deploy.getId()); * System.out.println("部署名稱:"+deploy.getName()); * System.out.println("部署時間:"+deploy.getDeploymentTime()); */ // System.out.println(count); for (Deployment deployment : list) { System.out.println("部署ID:" + deployment.getId()); System.out.println("部署名稱:" + deployment.getName()); System.out.println("部署時間:" + deployment.getDeploymentTime()); System.out.println("########################"); } } /** * 查詢流程定義 */ @Test public void queryProcDef() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery() // 條件 // .deploymentId(deploymentId) 根據(jù)部署ID查詢 // .deploymentIds(deploymentIds) 根據(jù)部署ID的集合查詢Set<String> deploymentIds // .processDefinitionId(processDefinitionId)//根據(jù)流程定義IDHelloWorld:1:4 // .processDefinitionIds(processDefinitionIds)//根據(jù)流程定義的IDS查詢 // .processDefinitionKey(processDefinitionKey)//根據(jù)流程定義的的key查詢 // .processDefinitionKeyLike(processDefinitionKeyLike)//根據(jù)流程定義的的key模糊查詢 // .processDefinitionName(processDefinitionName)//根據(jù)流程定義的名稱查詢 // .processDefinitionNameLike(processDefinitionNameLike)//根據(jù)流程定義的名稱模糊查詢 // .processDefinitionResourceName(resourceName)//根據(jù)流程圖的BPMN文件名查詢 // .processDefinitionResourceNameLike(resourceNameLike)//根據(jù)流程圖的BPMN文件名模糊查詢 // .processDefinitionVersion(processDefinitionVersion)//根據(jù)流程定義的版本查詢 // .processDefinitionVersionGreaterThan(processDefinitionVersion)//version>num // .processDefinitionVersionGreaterThanOrEquals(processDefinitionVersion)//version>=num // .processDefinitionVersionLowerThan(processDefinitionVersion)//version<num // .processDefinitionVersionLowerThanOrEquals(processDefinitionVersion)//version<=num // 排序 // .orderByDeploymentId() // .orderByProcessDefinitionId() // .orderByProcessDefinitionKey() // .orderByProcessDefinitionName() // .orderByProcessDefinitionVersion() // 結(jié)果集 .list(); // .listPage(firstResult, maxResults)\ // .count() // .singleResult() if (null != list && list.size() > 0) { for (ProcessDefinition pd : list) { System.out.println("流程定義ID:" + pd.getId()); System.out.println("流程部署ID:" + pd.getDeploymentId()); System.out.println("流程定義KEY:" + pd.getKey()); System.out.println("流程定義的名稱:" + pd.getName()); System.out.println("流程定義的bpmn文件名:" + pd.getResourceName());// bpmn的name System.out.println("流程圖片名:" + pd.getDiagramResourceName());// png的name System.out.println("流程定義的版本號:" + pd.getVersion()); System.out.println("##################"); } } } /** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this.processEngine.getRuntimeService(); String processDefinitionKey = "mytest"; runtimeService.startProcessInstanceByKey(processDefinitionKey); System.out.println("流程啟動成功"); } /** * 刪除流程定義 */ @Test public void deleteProcessDef() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); String deploymentId = "2501"; // 根據(jù)流程部署id刪除流程定義 如果當(dāng)前id的流程正在執(zhí)行,那么會報錯 // repositoryService.deleteDeployment(deploymentId); // 根據(jù)流程部署id刪除刪除流程定義 如果當(dāng)前id的流程正在執(zhí)行,會把正在執(zhí)行的流程數(shù)據(jù)刪除 act_ru_*和act_hi_*表里面的數(shù)據(jù) repositoryService.deleteDeployment(deploymentId, true); // repositoryService.deleteDeploymentCascade(deploymentId);==repositoryService.deleteDeployment(deploymentId, true); System.out.println("刪除成功"); } /** * 查詢流程圖 根據(jù)流程定義ID */ @Test public void viewProcessImg() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); String processDefinitionId = "mytest:2:2504"; InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); File file = new File("d:/mytest.png"); try { BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); outputStream.flush(); } outputStream.close(); inputStream.close(); System.out.println("查詢成功"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 查詢流程圖 根據(jù)流流程部署ID */ @Test public void viewProcessImg2() { RepositoryService repositoryService = this.processEngine.getRepositoryService(); // 根據(jù)流程部署ID查詢流程定義對象 String deploymentId = "1"; ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deploymentId).singleResult(); // 從流程定義對象里面查詢出流程定義ID String processDefinitionId = processDefinition.getId(); InputStream inputStream = repositoryService.getProcessDiagram(processDefinitionId); File file = new File("d:/" + processDefinition.getDiagramResourceName()); try { BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(file)); int len = 0; byte[] b = new byte[1024]; while ((len = inputStream.read(b)) != -1) { outputStream.write(b, 0, len); outputStream.flush(); } outputStream.close(); inputStream.close(); System.out.println("查詢成功"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 查詢最新的流程定義 */ @Test public void queryNewProcessDef() { Map<String, ProcessDefinition> map = new HashMap<>(); // 查詢所有的流程定義根據(jù)版本號升序 RepositoryService repositoryService = this.processEngine.getRepositoryService(); List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery() .orderByProcessDefinitionVersion().asc().list(); if (null != list && list.size() > 0) { for (ProcessDefinition pd : list) { map.put(pd.getKey(), pd); } } // 循環(huán)map集合 Collection<ProcessDefinition> values = map.values(); for (ProcessDefinition pd : values) { System.out.println("流程定義ID:" + pd.getId()); System.out.println("流程部署ID:" + pd.getDeploymentId()); System.out.println("流程定義KEY:" + pd.getKey()); System.out.println("流程定義的名稱:" + pd.getName()); System.out.println("流程定義的bpmn文件名:" + pd.getResourceName());// bpmn的name System.out.println("流程圖片名:" + pd.getDiagramResourceName());// png的name System.out.println("流程定義的版本號:" + pd.getVersion()); System.out.println("##################"); } } /** * 已知key 附加功能:刪除流程定義(刪除key相同的所有不同版本的流程定義) */ public void deleteAllSameVersion() { String processDefinitionKey = "mytest" ; RepositoryService repositoryService = this .processEngine.getRepositoryService(); // 根據(jù)流程定義的key查詢流程集合 List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery() .processDefinitionKey(processDefinitionKey).list(); if ( null != list && list.size() > 0 ) { for (ProcessDefinition pd : list) { repositoryService.deleteDeployment(pd.getDeploymentId(), true ); } } } } |
肯定還有人會問,上面的請假流程是走完了,但是沒有寫請假理由,請假天數(shù),如果是報銷單的話 還需要上傳報銷單據(jù)等,那么這個怎么解決呢?這個時候就需要activiti提供給我們的流程變量了,那么什么是流程變量呢?
流程變量在整個工作流中扮演很重要的作用。例如:請假流程中有請假天數(shù)、請假原因等一些參數(shù)都為流程變量的范圍。流程變量的作用域范圍是只對應(yīng)一個流程實例。也就是說各個流程實例的流程變量是不相互影響的。流程實例結(jié)束完成以后流程變量還保存在數(shù)據(jù)庫中(存放到流程變量的歷史表中)。圖中紅框的信息就是流程變量。
那么我們怎么設(shè)置流程變量呢,我們啟動流程的時候就可以設(shè)置流程變量了,見代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/** * 啟動流程 */ @Test public void startProcess() { RuntimeService runtimeService = this .processEngine.getRuntimeService(); String processDefinitionKey = "mytest" ; // ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey); //創(chuàng)建流程變量對象 Map<String,Object> variables= new HashMap<>(); variables.put( "請假天數(shù)" , 30 ); //int variables.put( "請假原因" , "結(jié)婚" ); variables.put( "請假時間" , new Date()); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables); System.out.println( "流程啟動成功:" + processInstance.getId() + " " + processInstance.getProcessDefinitionId() + " " + processInstance.getProcessInstanceId()); } |
說明:
1)流程變量的作用域就是流程實例,所以只要設(shè)置就行了,不用管在哪個階段設(shè)置
2)基本類型設(shè)置流程變量,在taskService中使用任務(wù)ID,定義流程變量的名稱,設(shè)置流程變量的值。
3)Javabean類型設(shè)置獲取流程變量,除了需要這個javabean實現(xiàn)了Serializable接口外,還要求流程變量對象的屬性不能發(fā)生變化,否則拋出異常。解決方案,固定序列化ID
4)設(shè)置流程變量的時候,向act_ru_variable這個表添加數(shù)據(jù)
RuntimeService對象可以設(shè)置流程變量和獲取流程變量 TaskService對象可以設(shè)置流程變量和獲取流程變量
Map集合的key表示流程變量的名稱 Map集合的value表示流程變量的值
查詢流程變量以及查詢歷史流程變量:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/** * 獲取流程變量 */ @Test public void getVariables() { RuntimeService runtimeService = this .processEngine.getRuntimeService(); String executionId= "2501" ; Integer days=(Integer) runtimeService.getVariable(executionId, "請假天數(shù)" ); Date date=(Date) runtimeService.getVariable(executionId, "請假時間" ); User user=(User) runtimeService.getVariable(executionId, "用戶對象" ); System.out.println(days); System.out.println(date.toLocaleString()); System.out.println(user.getId()+ " " +user.getName()); } /** * 7:查詢歷史的流程變量 */ @Test public void getHistoryVariables() { HistoryService historyService = this .processEngine.getHistoryService(); /*HistoricVariableInstance singleResult = historyService.createHistoricVariableInstanceQuery().id("2503").singleResult();; System.out.println(singleResult.getId()); System.out.println(singleResult.getValue()); System.out.println(singleResult.getVariableName()); System.out.println(singleResult.getVariableTypeName());*/ String processInstanceId= "2501" ; List<HistoricVariableInstance> list = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list(); for (HistoricVariableInstance hvs : list) { System.out.println( "ID" +hvs.getId()); System.out.println( "變量值" +hvs.getValue()); System.out.println( "變量名" +hvs.getVariableName()); System.out.println( "變量類型" +hvs.getVariableTypeName()); System.out.println( "#####################" ); } } |
查詢歷史流程實例 、查詢歷史活動 以及查詢歷史任務(wù)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
public class TestHistoryQuery { private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine(); HistoryService historyService = this .processEngine.getHistoryService(); /* 1,查詢歷史流程實例 */ @Test public void historyProcessInstince() { List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery() //條件 // .processDefinitionId(processDefinitionId) // .processDefinitionKey(processDefinitionKey) // .processDefinitionKeyIn(processDefinitionKeys) // .processDefinitionName(processDefinitionName) // .processDefinitionVersion(processDefinitionVersion) // .processInstanceBusinessKey(processInstanceBusinessKey) // .processInstanceId(processInstanceId) // .processInstanceIds(processInstanceIds) //排序 // .orderByProcessDefinitionId() // .orderByProcessInstanceBusinessKey() // .orderByProcessInstanceDuration() // .orderByProcessInstanceStartTime() // .orderByProcessInstanceId() //結(jié)果集 .list(); // .listPage(firstResult, maxResults) // .count() // .singleResult(); if(null!=list&&list.size()>0) { for (HistoricProcessInstance hpi : list) { System.out.println("歷史流程實例ID:" + hpi.getId()); System.out.println("流程定義ID:" + hpi.getProcessDefinitionId()); System.out.println("歷史流程實例的業(yè)務(wù)ID:" + hpi.getBusinessKey()); System.out.println("流程部署ID:" + hpi.getDeploymentId()); System.out.println("流程定義KEY:" + hpi.getProcessDefinitionKey()); System.out.println("開始活動ID:" + hpi.getStartActivityId()); System.out.println("結(jié)束活動ID:" + hpi.getEndActivityId()); System.out.println("########################"); } } } /* 2,查詢歷史活動 */ @Test public void queryHistoryAct() { List<HistoricActivityInstance> list = this.historyService.createHistoricActivityInstanceQuery() //條件 // .activityId(activityId) // .activityInstanceId(activityInstanceId) // .activityName(activityName) //排序 // .orderByActivityId() // .orderByActivityName() //結(jié)果集 .list(); if(null!=list&&list.size()>0) { for (HistoricActivityInstance hai : list) { System.out.println("ID:"+hai.getId()); System.out.println("流程定義ID:"+hai.getProcessDefinitionId()); System.out.println("流程實例ID:"+hai.getProcessInstanceId()); System.out.println("執(zhí)行實例ID:"+hai.getExecutionId()); System.out.println("活動ID:"+hai.getActivityId()); System.out.println("任務(wù)ID:"+hai.getTaskId()); System.out.println("活動名稱:"+hai.getActivityName()); System.out.println("活動類型:"+hai.getActivityType()); System.out.println("任務(wù)辦理人:"+hai.getAssignee()); System.out.println("開始時間:"+hai.getStartTime()); System.out.println("結(jié)束時間:"+hai.getEndTime()); System.out.println("持續(xù)時間:"+hai.getDurationInMillis()); System.out.println("#######################################"); } } } /* 3,查詢歷史任務(wù) act_hi_taskinst */ @Test public void queryHistoryTask() { List<HistoricTaskInstance> list = this .historyService.createHistoricTaskInstanceQuery() //條件 // .deploymentId(deploymentId) // .deploymentIdIn(deploymentIds) // .executionId(executionId) // .processDefinitionId(processDefinitionId) // .processDefinitionKey(processDefinitionKey) // .processDefinitionKeyIn(processDefinitionKeys) // .processDefinitionKeyLike(processDefinitionKeyLike) processDefinitionKeyLike="%Hello%" // .processDefinitionName(processDefinitionName) // .processDefinitionNameLike(processDefinitionNameLike) //排序 // .orderByTaskDefinitionKey() //結(jié)果集 .list(); // .listPage(firstResult, maxResults) // .count() // .singleResult() if ( null !=list&&list.size()> 0 ) { for (HistoricTaskInstance task : list) { System.out.println( "任務(wù)ID:" + task.getId()); System.out.println( "任務(wù)辦理人:" + task.getAssignee()); System.out.println( "執(zhí)行實例ID:" + task.getExecutionId()); System.out.println( "任務(wù)名稱:" + task.getName()); System.out.println( "流程定義ID:" + task.getProcessDefinitionId()); System.out.println( "流程實例ID:" + task.getProcessInstanceId()); System.out.println( "任務(wù)創(chuàng)建時間:" + task.getCreateTime()); System.out.println( "任務(wù)結(jié)束時間:" + task.getEndTime()); System.out.println( "#######################################" ); } } } } |
最近我發(fā)現(xiàn)上面的代碼不能完全在開發(fā)中應(yīng)用,比如上面的用戶申請是在畫流程圖的時候?qū)懰赖模趯嶋H開發(fā)中肯定是根據(jù)當(dāng)前登錄的用戶來提出申請,另外還沒有分支的情況,所以我特地修改了一下流程圖。
這個流程圖中 沒有設(shè)置用戶,在Condition中傳入?yún)?shù)#{UserId},后面的重要與不重要分支同樣加上Condition條件${message=='重要'}和${message=='不重要'},然后主管審核和總經(jīng)理的assignee可以設(shè)置成固定的值也可以像用戶一樣根據(jù)傳參設(shè)置。接下來直接上代碼
1.啟動流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/**啟動流程實例*/ @Test public void startProcessInstance(){ String processDefinitionKey = "myProcess_1" ; /**啟動流程實例的同時,設(shè)置流程變量,使用流程變量用來指定任務(wù)的辦理人,對應(yīng)task.pbmn文件中#{userID}*/ Map<String, Object> variables = new HashMap<String, Object>(); variables.put( "userID" , "袁志豪" ); ProcessInstance pi = processEngine.getRuntimeService() //與正在執(zhí)行的流程實例和執(zhí)行對象相關(guān)的Service .startProcessInstanceByKey(processDefinitionKey,variables); //使用流程定義的key啟動流程實例,key對應(yīng)helloworld.bpmn文件中id的屬性值,使用key值啟動,默認(rèn)是按照最新版本的流程定義啟動 System.out.println( "流程實例ID:" +pi.getId()); //流程實例ID 101 System.out.println( "流程定義ID:" +pi.getProcessDefinitionId()); //流程定義ID } |
用戶完成申請?zhí)峤唬鞴茉诹鞒蓤D中沒有設(shè)置固定值
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Test public void completeTask() { TaskService taskService = this .processEngine.getTaskService(); String taskId = "2508" ; // 根據(jù)任務(wù)ID去完成任務(wù) // taskService.complete(taskId); // 根據(jù)任務(wù)ID去完成任務(wù)并指定流程變量 Map<String,Object > variable = new HashMap<>(); String shenheren = "張三" ; //實際開發(fā)中可在前臺選擇主管傳入后臺 variable.put( "zhuguan" , "張三" ); //這里的 zhuguan 和 activiti.bpmn中的#{zhuguan}保持一致,既可以設(shè)置下一級審核主管 taskService.complete(taskId, variables); System.out.println( "任務(wù)完成" ); } |
主管審核
1
2
3
4
5
6
7
8
9
10
|
@Test public void complateTask2(){ TaskService taskService = this .processEngine.getTaskService(); String taskId2= "5002" ; Map<String,Object > variable = new HashMap<>(); /***這里的message 是流程圖中分支條件message,根據(jù)傳入的參數(shù)判斷走那一條線***/ variable.put( "message" , "重要" ); // variable.put("message","不重要"); taskService.complete(taskId2,variable); } |
經(jīng)理審核
1
2
3
4
5
6
7
8
|
@Test public void complateTask3(){ TaskService taskService = this .processEngine.getTaskService(); String taskId2= "7503" ; Map<String,Object > variable = new HashMap<>(); variable.put( "審核意見" , "好好休假注意身體" ); //領(lǐng)導(dǎo)審核意見 taskService.complete(taskId2,variable); } |
另外我在開發(fā)中發(fā)現(xiàn)在流程圖畫完之后將bpmn后綴改為xml方式生成圖片之后,再次改為bpmn的時候,發(fā)現(xiàn)之前寫的Condition中變成了\n,如圖
我們再次將后綴改為xml之后查看我們的條件:
解決方式:
將condition前面后面的空格刪掉即可;
到此這篇關(guān)于關(guān)于在IDEA中SpringBoot項目中activiti工作流的使用詳解的文章就介紹到這了,更多相關(guān)IDEA SpringBoot activiti工作流內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/weixin_38340467/article/details/107811648