基于Spring Cloud应用activiti流程框架
activiti工作流简介
Activiti 是一个开源架构的工作流引擎,基于bpmn2.0 标准进行流程定义。其前身是JBPM,Activiti 通过嵌入到业务系统开发中进行使用。
引入与使用
- 1.maven pom.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<!-- 引入Activiti7 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M4</version>
<!-- 7.1.0版本排除mybatis 防止冲突 -->
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.1.0.M4</version>
<type>pom</type>
</dependency>
<!-- 生成流程图 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>7.1.0.M4</version>
</dependency> - 2.yml配置文件编写
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
51server:
port: 16666
spring:
application:
name: activity
datasource:
name: test
url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/activity?useUnicode=true&characterEncoding=UTF8&useSSL=false
username: activity
password: activity
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
activiti:
#关闭activiti自动部署(使用流程设计器部署,不使用具体文件访问方式)
check-process-definitions: false
#设置流程引擎启动和关闭时数据库执行的策略
#false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果版本不匹配时,将在启动时抛出异常。
#true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
#create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
#drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。
database-schema-update: true
#保存历史数据级别设置为full最高级别,便于历史数据的追溯
#none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
#activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
#audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
#full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
history-level: full
management:
endpoints:
web:
base-path: /
logging:
level:
com.acti: DEBUG - 3.启动类配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package com.acti;
import org.activiti.spring.boot.SecurityAutoConfiguration;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Desc activity
* @Author jx111
* @Date 2019/11/29-16:28
*/
public class ActivityApplication {
public static void main(String[] args) {
SpringApplication.run(ActivityApplication.class, args);
}
}注:@SpringBootApplication(exclude = { SecurityAutoConfiguration.class}) 排除注解,取消登陆限制。
启动服务后,可在数据库中观察到表名以act_为首的25张表生成。
整合发布
spring cloud整合SpringSecurity
- 1.添加工具类
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
86package com.czq.image.util;
//import com.czq.image.dao.UserRepository.java;
import com.czq.image.dao.SysUserRepository;
//import com.czq.image.service.impl.MyUserD??etailsService;
import com.czq.model.image.entity.SysUserEntity;
import io.swagger.annotations.AuthorizationScope;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.security.Permission;
import java.util.*;
public class SecurityUtil {
private final UserDetailsService userDetailsService;
// public SecurityUtil() {
//
// }
public void logInAs(String username) {
UserDetails user = userDetailsService.loadUserByUsername(username);
if (user == null) {
throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
}
SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthorities();
}
public Object getCredentials() {
return user.getPassword();
}
public Object getDetails() {
return user;
}
public Object getPrincipal() {
return user;
}
public boolean isAuthenticated() {
return true;
}
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
public String getName() {
return user.getUsername();
}
}));
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
}
} - 2.添加配置类
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
127package com.czq.image.config;
//import com.czq.image.service.impl.MyUserDetailsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {
private final Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService());
}
public UserDetailsService myUserDetailsService() {
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
String[][] usersGroupsAndRoles = {
{"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
{"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
{"admin", "password", "ROLE_ACTIVITI_ADMIN"},
};
for (String[] user : usersGroupsAndRoles) {
List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
}
return inMemoryUserDetailsManager;
}
protected void configure(HttpSecurity http) throws Exception {
http
//
.csrf().disable()
.authorizeRequests()
.anyRequest().permitAll()
// .authenticated()
.and()
// .cors()
// .and().
.httpBasic();
// .and()
// .cors(c -> {
// CorsConfigurationSource source = request -> {
// CorsConfiguration config = new CorsConfiguration();
// config.setAllowedOrigins(Arrays.asList("*"));
// config.setAllowedMethods(Arrays.asList("*"));
// return config;
// };
// c.configurationSource(source);
// });
}
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**","/resources/**","/templates/**","/lib/**","/file/**","/img/**","/swagger-ui.html");
}
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("PUT", "DELETE", "GET", "POST", "OPTIONS", "HEAD"));
configuration.setAllowCredentials(true);
configuration.setExposedHeaders(Arrays.asList( "access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin",
"access-Control-allow-credentials",
"access-control-max-age",
"X-Frame-Options"));
configuration.setAllowedHeaders(Arrays.asList("Content-Type", "X-Requested-With", "accept", "Authorization", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"));
configuration.setMaxAge(3600L);
// configuratio
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowUrlEncodedSlash(true);
return firewall;
}
}
bpnm文件绘制生成
- 1.demo.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
28
29
30
31
32
33
34
35
36
37
38
39
40
<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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="myProcess_1" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="one" activiti:candidateGroups="activitiTeam"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<userTask id="usertask2" name="two" activiti:candidateGroups="activitiTeam"></userTask>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_myProcess_1">
<bpmndi:BPMNPlane bpmnElement="myProcess_1" id="BPMNPlane_myProcess_1">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="50.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="130.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="280.0" y="150.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="430.0" y="160.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="85.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="130.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="235.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="280.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="385.0" y="177.0"></omgdi:waypoint>
<omgdi:waypoint x="430.0" y="177.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
接口定义与使用
- 1.接口定义
API文件接口编写
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
50package com.czq.api.image;
//import com.czq.common.model.response.Result;
import com.czq.model.image.entity.Result;
import com.czq.model.image.request.AddXMLRequest;
//import com.czq.model.image.response.Result;
import com.czq.model.user.UserMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
public interface BPMNControllerApi {
public Result postBPMNAndDeployment(AddXMLRequest addXMLRequest);
public Result uploadFileAndDeployment(
MultipartFile processFile,
String processName);
public void getProcessDefineXML(String deploymentId, String resourceName, HttpServletResponse response);
public Result startProcess(
String processDefinitionKey,
String instanceName,
UserMessage userDetail);
public Result suspendInstance(String instanceId);
public Result resumeInstance(String instanceId);
public Result completeTask(String taskId);
public Result getTasks();
public Result testActiviti();
} - 2.controller中调用service实现功能
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
80package com.czq.image.controller;
import com.czq.api.image.BPMNControllerApi;
//import com.czq.common.model.response.Result;
import com.czq.image.service.BPMNService;
import com.czq.model.image.entity.Result;
import com.czq.model.image.request.AddXMLRequest;
//import com.czq.model.image.response.Result;v/
import com.czq.model.user.UserMessage;
import org.activiti.api.task.model.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
public class BPMNController implements BPMNControllerApi {
BPMNService bpmnService;
public Result postBPMNAndDeployment( { AddXMLRequest addXMLRequest)
return bpmnService.postBPMNAndDeployment(addXMLRequest);
}
public Result uploadFileAndDeployment(
MultipartFile processFile,
{ String processName)
return bpmnService.uploadFileAndDeployment(processFile,processName);
}
public void getProcessDefineXML(String deploymentId, String resourceName, HttpServletResponse response) {
bpmnService.getProcessDefineXML(deploymentId,resourceName,response);
}
public Result startProcess(String processDefinitionKey, String instanceName, UserMessage userDetail) {
return bpmnService.startProcess(processDefinitionKey,instanceName,userDetail);
}
public Result suspendInstance({ String instanceId)
return bpmnService.suspendInstance(instanceId);
}
public Result resumeInstance({ String instanceId)
return bpmnService.resumeInstance(instanceId);
}
public Result completeTask({ String taskId)
return bpmnService.completeTask(taskId);
}
public Result getTasks() {
return bpmnService.getTasks();
}
public Result testActiviti() {
return bpmnService.testActiviti();
}
} - 3.编写Controller调用的服务,服务通过调用activiti框架提供接口完成各项功能
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
package com.czq.image.service.impl;
import com.czq.common.model.response.CommonCode;
//import com.czq.common.model.response.Result;
import com.czq.image.service.BPMNService;
import com.czq.image.util.SecurityUtil;
import com.czq.model.image.entity.Result;
import com.czq.model.image.entity.vo.HistoricActivityInstanceVO;
import com.czq.model.image.entity.vo.TaskVO;
import com.czq.model.image.entity.vo.VOConverter;
import com.czq.model.image.request.AddXMLRequest;
//import com.czq.model.image.response.Result;/
import com.czq.model.user.UserMessage;
import org.activiti.api.process.model.ProcessDefinition;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.model.payloads.StartProcessPayload;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.*;
import org.activiti.engine.repository.Deployment;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipInputStream;
public class BPMNServiceImpl implements BPMNService {
RepositoryService repositoryService;
ProcessRuntime processRuntime;
TaskRuntime taskRuntime;
RuntimeService runtimeService;
HistoryService historyService;
private final Logger logger = LoggerFactory.getLogger(BPMNServiceImpl.class);
// @Autowired
// private ProcessRuntime processRuntime;
// @Autowired
// private TaskRuntime taskRuntime;
public Result postBPMNAndDeployment(AddXMLRequest addXMLRequest) {
Deployment deploy = repositoryService.createDeployment()
// .addString 第一次参数的名字如果没有添加.bpmn的话,不会插入到 ACT_RE_DEPLOYMENT 表中
.addString(addXMLRequest.getProcessName() + ".bpmn", addXMLRequest.getBpmnContent())
.name(addXMLRequest.getProcessName())
.deploy();
return Result.ok(deploy);
}
public Result uploadFileAndDeployment(MultipartFile processFile,
String processName) {
String originalFilename = processFile.getOriginalFilename();
String extension = FilenameUtils.getExtension(originalFilename);
if (processName != null) {
processName = originalFilename;
}
try {
InputStream inputStream = processFile.getInputStream();
Deployment deployment = null;
if ("zip".equals(extension)) {
// 压缩包部署方式
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
deployment = repositoryService.createDeployment().addZipInputStream(zipInputStream).name(processName).deploy();
} else if ("bpmn".equals(extension)) {
// bpmn文件部署方式
deployment = repositoryService.createDeployment().addInputStream(originalFilename, inputStream).name(processName).deploy();
}
return Result.ok(deployment);
} catch (IOException e) {
e.printStackTrace();
}
return Result.error("deployment object null !");
}
public void getProcessDefineXML(String deploymentId, String resourceName, HttpServletResponse response) {
try {
InputStream inputStream = repositoryService.getResourceAsStream(deploymentId, resourceName);
int count = inputStream.available();
byte[] bytes = new byte[count];
response.setContentType("text/xml");
OutputStream outputStream = response.getOutputStream();
while (inputStream.read(bytes) != -1) {
outputStream.write(bytes);
}
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public Result startProcess(String processDefinitionKey, String instanceName, UserMessage userDetail) {
ProcessInstance processInstance = null;
try {
StartProcessPayload startProcessPayload = ProcessPayloadBuilder.start().withProcessDefinitionKey(processDefinitionKey)
.withBusinessKey("businessKey")
.withVariable("sponsor", userDetail.getUsername())
.withName(instanceName).build();
processInstance = processRuntime.start(startProcessPayload);
} catch (Exception e) {
e.printStackTrace();
// System.out.println(e);
return Result.error(e.getMessage());
}
return Result.ok(processInstance);
}
public Result suspendInstance(String instanceId) {
ProcessInstance processInstance = processRuntime.suspend(ProcessPayloadBuilder.suspend().withProcessInstanceId(instanceId).build());
return Result.ok(processInstance);
}
public Result resumeInstance(String instanceId) {
ProcessInstance processInstance = processRuntime
.resume(ProcessPayloadBuilder.resume().withProcessInstanceId(instanceId).build());
return Result.ok(processInstance);
}
public Result completeTask(String taskId) {
Task task = taskRuntime.task(taskId);
if (task.getAssignee() == null) {
// 说明任务需要拾取
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(taskId).build());
}
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).build());
return Result.ok(task);
}
public Result getTasks() {
// SecurityUtil securityUtil = new SecurityUtil();
// securityUtil.logInAs("jack");
// Page<Task> taskPage = runtimeService.(Pageable.of(0,100));
Page<Task> taskPage = taskRuntime.tasks(Pageable.of(0, 100));
List<Task> tasks = taskPage.getContent();
List<TaskVO> taskVOS = new ArrayList<>();
for (Task task : tasks) {
TaskVO taskVO = (TaskVO) task;
// TaskVO taskVO = TaskVO.o/ftask;
ProcessInstance instance = processRuntime.processInstance(task.getProcessInstanceId());
taskVO.setInstanceName(instance.getName());
taskVOS.add(taskVO);
}
return Result.ok(taskVOS);
}
public UserDetails createLoginUser(UserMessage user) {
// Set<String> postCode = sysPostService.selectPostCodeByUserId(user.getId());
// postCode = postCode.parallelStream().map( s -> "GROUP_" + s).collect(Collectors.toSet());
// postCode.add("ROLE_ACTIVITI_USER");
// List<SimpleGrantedAuthority> collect = postCode.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList());
// return new LoginUser(user, permissionService.getMenuPermission(user), collect);
return null;
}
public Result testActiviti() {
// 首先,取出项目中的最多 10 个流程定义
Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
if (processDefinitionPage.getTotalItems() > 0) {
// 然后,对取出的流程进行启动
for (ProcessDefinition definition : processDefinitionPage.getContent()) {
logger.info(" 流程定义信息:" + definition);
processRuntime.start(ProcessPayloadBuilder
.start()
.withProcessDefinitionId(definition.getId())
.build());
}
}
// 完成流程启动后,由于当前项目中只有 other.bpmn 一个流程,且该流程在设计时,已分配给activitiTeam 组
// 因此我们登录一个 activitiTeam 组成员 , 该账号信息会被设置到 security 上下文中,activiti会对其信息进行读取
// 获取当前用户任务,最多 10 个
Page<Task> taskPage = taskRuntime.tasks(Pageable.of(0, 10));
// 由于目前只有一个流程,两个任务,我们尝试一下完成一个,看看会发生什么变化
if (taskPage.getTotalItems() > 0) {
for (Task task : taskPage.getContent()) {
logger.info(" 任务信息1:" + task);
// 注意,完成任务前必须先声明
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
// 完成任务
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build()
);
}
}
// 上一轮任务完成,再看一下,现在流程是否走到了 second ?
taskPage = taskRuntime.tasks(Pageable.of(0, 10));
if (taskPage.getTotalItems() > 0) {
for (Task task : taskPage.getContent()) {
logger.info("任务2: " + task);
}
}
return Result.ok(taskPage);
}
/**
* @param businessKey
* @desc 查询历史记录
**/
public List<HistoricActivityInstanceVO> getProcessHistoryByBusinessKey(String businessKey) {
ProcessInstance instance = (ProcessInstance) runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(instance.getId())
.orderByHistoricActivityInstanceStartTime().asc().list();
List<HistoricActivityInstanceVO> historicActivityInstanceVOList = new ArrayList<>();
historicActivityInstanceList.forEach(historicActivityInstance -> historicActivityInstanceVOList.add(VOConverter.getHistoricActivityInstanceVO(historicActivityInstance)));
String instanceId = "111";
String taskId = "111";
// 详情查询+
HistoricDetailQuery historicDetailQuery = historyService.createHistoricDetailQuery();
List<HistoricDetail> historicDetails = historicDetailQuery.processInstanceId(instanceId).orderByTime().list();
for (HistoricDetail hd : historicDetails) {
System.out.println("流程实例ID:" + hd.getProcessInstanceId());
System.out.println("活动实例ID:" + hd.getActivityInstanceId());
System.out.println("执行ID:" + hd.getTaskId());
System.out.println("记录时间:" + hd.getTime());
}
// 任务历史流程查询
HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
List<HistoricTaskInstance> taskInstances = historicTaskInstanceQuery.taskId(taskId).list();
for (HistoricTaskInstance hti : taskInstances) {
System.out.println("开始时间:" + hti.getStartTime());
System.out.println("结束时间:" + hti.getEndTime());
System.out.println("任务拾取时间:" + hti.getClaimTime());
System.out.println("删除原因:" + hti.getDeleteReason());
}
return historicActivityInstanceVOList;
}
}
测试
- 1.demo
1
curl -l http://localhost:16666/api/v1.0.1/bpmn/gettask
- 2.返回值
1
2
3
4
5
6{
"msg": "Success!",
"code": 200,
"obj": [],
"success": true
}