1 Activiti和Spring整合开发#
1.1 Activiti和Spring整合的配置#
<properties >
<activiti.version > 7.0.0.GA</activiti.version >
</properties >
<dependencies >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-engine</artifactId >
<version > 7.0.0.GA</version >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-spring</artifactId >
<version > ${activiti.version}</version >
</dependency >
<dependency >
<groupId > org.springframework</groupId >
<artifactId > spring-test</artifactId >
<version > 5.1.4.RELEASE</version >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-bpmn-model</artifactId >
<version > ${activiti.version}</version >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-bpmn-converter</artifactId >
<version > ${activiti.version}</version >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-json-converter</artifactId >
<version > ${activiti.version}</version >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-bpmn-layout</artifactId >
<version > ${activiti.version}</version >
</dependency >
<dependency >
<groupId > org.activiti.cloud</groupId >
<artifactId > activiti-cloud-services-api</artifactId >
<version > 7-201802-EA</version >
</dependency >
<dependency >
<groupId > mysql</groupId >
<artifactId > mysql-connector-java</artifactId >
<version > 8.0.19</version >
</dependency >
<dependency >
<groupId > junit</groupId >
<artifactId > junit</artifactId >
<version > 4.12</version >
</dependency >
<dependency >
<groupId > org.apache.logging.log4j</groupId >
<artifactId > log4j-core</artifactId >
<version > 2.13.3</version >
</dependency >
<dependency >
<groupId > org.apache.logging.log4j</groupId >
<artifactId > log4j-api</artifactId >
<version > 2.13.3</version >
</dependency >
<dependency >
<groupId > org.slf4j</groupId >
<artifactId > slf4j-api</artifactId >
<version > 1.7.30</version >
</dependency >
<dependency >
<groupId > org.apache.logging.log4j</groupId >
<artifactId > log4j-slf4j-impl</artifactId >
<version > 2.13.3</version >
</dependency >
<dependency >
<groupId > org.mybatis</groupId >
<artifactId > mybatis</artifactId >
<version > 3.4.5</version >
</dependency >
<dependency >
<groupId > commons-dbcp</groupId >
<artifactId > commons-dbcp</artifactId >
<version > 1.4</version >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.activiti.cloud.dependencies</groupId >
<artifactId > activiti-cloud-dependencies</artifactId >
<version > 7.0.0.GA</version >
<scope > import</scope >
<type > pom</type >
</dependency >
</dependencies >
</dependencyManagement >
创建Spring和Activiti的整合配置文件activiti-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context ="http://www.springframework.org/schema/context"
xmlns ="http://www.springframework.org/schema/beans"
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" >
<bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" >
<property name ="driverClassName" value ="com.mysql.cj.jdbc.Driver" />
<property name ="username" value ="root" />
<property name ="url"
value ="jdbc:mysql://192.168.1.146:3306/activiti?useUnicode=true& characterEncoding=UTF-8& autoReconnect=true& useSSL=false& serverTimezone=GMT%2B8& allowPublicKeyRetrieval=true" />
<property name ="password" value ="123456" />
<property name ="maxActive" value ="3" />
<property name ="maxIdle" value ="1" />
</bean >
<bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name ="dataSource" ref ="dataSource" />
</bean >
<bean id ="processEngineConfiguration" class ="org.activiti.spring.SpringProcessEngineConfiguration" >
<property name ="dataSource" ref ="dataSource" />
<property name ="transactionManager" ref ="transactionManager" />
<property name ="databaseSchemaUpdate" value ="true" />
</bean >
<bean id ="processEngine" class ="org.activiti.spring.ProcessEngineFactoryBean" >
<property name ="processEngineConfiguration" ref ="processEngineConfiguration" />
</bean >
<bean id ="repositoryService" factory-bean ="processEngine"
factory-method ="getRepositoryService" />
<bean id ="runtimeService" factory-bean ="processEngine"
factory-method ="getRuntimeService" />
<bean id ="taskService" factory-bean ="processEngine"
factory-method ="getTaskService" />
<bean id ="historyService" factory-bean ="processEngine"
factory-method ="getHistoryService" />
</beans >
<?xml version="1.0" encoding="UTF-8"?>
<configuration status ="INFO" >
<appenders >
<console name ="Console" target ="SYSTEM_OUT" >
<PatternLayout pattern ="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</console >
</appenders >
<loggers >
<root level ="INFO" >
<appender-ref ref ="Console" />
</root >
</loggers >
</configuration >
1.2 测试Activiti和Spring的整合#
package com.sunxiaping.test;
import org.activiti.engine.RepositoryService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:activiti-spring.xml"})
public class Activiti7Test {
@Autowired
private RepositoryService repositoryService;
@Test
public void test () {
System.out.println("repositoryService = " + repositoryService);
}
}
2 Activiti7和SpringBoot的整合开发#
2.1 概述#
Activiti7发布正式版以后,它可以和SpringBoot2.x完全整合。我们可以将Activiti7和SpringBoot整合开发的坐标引入到工程中,从而达到SpringBoot支持Activiti7。
SpringBoot整合Activiti7的具体步骤如下:
1️⃣添加SpringBoot整合Activiti7的jar包的坐标。
2️⃣添加SpringSecurity安全框架的整合配置信息。
3️⃣使用Activiti7新支持的接口(ProcessRuntime接口和TaskRuntime接口)来实现工作流开发。
4️⃣使用新的API实现工作流的开发,主要包括:流程定义查询,启动流程实例,任务的查询,任务的完成。
2.2 Activiti和SpringBoot整合的配置#
<parent >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-parent</artifactId >
<version > 2.2.9.RELEASE</version >
<relativePath />
</parent >
<dependencies >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-jdbc</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-test</artifactId >
<scope > test</scope >
</dependency >
<dependency >
<groupId > org.activiti</groupId >
<artifactId > activiti-spring-boot-starter</artifactId >
<version > 7.0.0.GA</version >
</dependency >
<dependency >
<groupId > org.mybatis.spring.boot</groupId >
<artifactId > mybatis-spring-boot-starter</artifactId >
<version > 2.1.3</version >
</dependency >
<dependency >
<groupId > mysql</groupId >
<artifactId > mysql-connector-java</artifactId >
</dependency >
</dependencies >
<build >
<plugins >
<plugin >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-maven-plugin</artifactId >
<version > 2.2.9.RELEASE</version >
</plugin >
</plugins >
</build >
spring:
datasource:
url: jdbc:mysql://192.168.134.100:3306/activiti?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username : root
password : 123456
driver-class-name: com.mysql.cj.jdbc.Driver
activiti:
database-schema-update: true
db-history-used: true
history-level: full
check-process-definitions: false
async-executor-activate: true
package com.sunxiaping.activiti7.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.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 java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private Logger logger = LoggerFactory.getLogger(SpringSecurityConfig.class);
@Override
public void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
}
@Bean
public UserDetailsService userDetailsService () {
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;
}
@Override
protected void configure (HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
@Bean
public PasswordEncoder passwordEncoder () {
return new BCryptPasswordEncoder ();
}
}
package com.sunxiaping.activiti7.service;
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.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.stereotype.Component;
import java.util.Collection;
@Component
public class UserService {
@Qualifier("userDetailsService")
@Autowired
private UserDetailsService userDetailsService;
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 () {
@Override
public Collection<? extends GrantedAuthority > getAuthorities() {
return user.getAuthorities();
}
@Override
public Object getCredentials () {
return user.getPassword();
}
@Override
public Object getDetails () {
return user;
}
@Override
public Object getPrincipal () {
return user;
}
@Override
public boolean isAuthenticated () {
return true ;
}
@Override
public void setAuthenticated (boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName () {
return user.getUsername();
}
}));
org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
}
}
package com.sunxiaping.activiti7;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Activiti7SpringBootApplication {
public static void main (String[] args) {
SpringApplication.run(Activiti7SpringBootApplication.class, args);
}
}
2.3 测试Activiti和SpringBoot的整合#
package com.sunxiaping.activiti7;
import com.sunxiaping.activiti7.service.UserService;
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.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.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Activiti7SpringBootApplication.class)
public class Activiti7Test {
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private UserService userService;
@Test
public void testQueryProcessDefinition () {
userService.logInAs("salaboy" );
Page<ProcessDefinition> page = processRuntime.processDefinitions(Pageable.of(0 , 10 ));
int totalItems = page.getTotalItems();
System.out.println("查看部署流程的个数 = " + totalItems);
List<ProcessDefinition> content = page.getContent();
for (ProcessDefinition processDefinition : content) {
String id = processDefinition.getId();
System.out.println("当前部署的流程定义的id = " + id);
}
}
@Test
public void testStartProcessInstance () {
userService.logInAs("salaboy" );
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("team01" ).build());
System.out.println("流程实例的id = " + processInstance.getId());
}
@Test
public void testQueryTask () {
userService.logInAs("salaboy" );
Page<Task> page = taskRuntime.tasks(Pageable.of(0 , 10 ));
int totalItems = page.getTotalItems();
System.out.println("任务的总数 = " + totalItems);
for (Task task : page.getContent()) {
String id = task.getId();
System.out.println("任务的id = " + id);
String name = task.getName();
System.out.println("任务名称 = " + name);
}
}
@Test
public void testQueryTaskAndCompleteTask () {
userService.logInAs("salaboy" );
Page<Task> page = taskRuntime.tasks(Pageable.of(0 , 10 ));
int totalItems = page.getTotalItems();
System.out.println("任务的总数 = " + totalItems);
for (Task task : page.getContent()) {
String id = task.getId();
System.out.println("任务的id = " + id);
String name = task.getName();
System.out.println("任务名称 = " + name);
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(id).build());
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(id).build());
}
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性