本篇文章为你整理了Activiti7+SpringBoot()的详细内容,包含有 Activiti7+SpringBoot,希望能帮助你了解 Activiti7+SpringBoot。
1.1. Activiti版本
7.1.0-M6是最后一个支持JDK1.8的版本,此后的版本都要求JDK11以上
目前,Activiti最新版本是7.6.0,它是用JDK11编译的,因此要想使用最新版7.6.0必须升级JDK版本,不能再用1.8
同时,7.6.0依赖的SpringBoot版本是2.7.5
1.2. SpringBoot版本
最新的SpringBoot版本是3.0.0,这个版本不支持JDK1.8,对JDK的最小版本是17
目前可用比较多的Java版本是Java 17 和 Java 19
综合来看,我们采用Java 17+SpringBoot 2.7.5+Activiti 7.6.1
补充:52 = Java 8 55 = Java 11
2. Maven仓库设置
首先要添加Activiti组件的仓库,不然找不到jar包,可用配置在全局的settings.xml文件中,也可以配置在项目pom.xml中
repositories
repository
id activiti-releases /id
url https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases /url
/repository
/repositories
如果settings.xml中有镜像,并且所有镜像都使用一个仓库的话(即,morrorOf配置的是*),要注意将新加的这个仓库排除
https://maven.apache.org/guides/mini/guide-mirror-settings.html
举个例子:
3. 依赖管理
Activiti依赖管理
dependencyManagement
dependencies
dependency
groupId org.activiti /groupId
artifactId activiti-dependencies /artifactId
version 7.6.1 /version
scope import /scope
type pom /type
/dependency
/dependencies
/dependencyManagement
Dubbo依赖管理
dependencyManagement
dependencies
dependency
groupId org.apache.dubbo /groupId
artifactId dubbo-bom /artifactId
version 3.1.3 /version
scope import /scope
type pom /type
/dependency
/dependencies
/dependencyManagement
完整的父POM如下:
?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 3.0.0 /version --
version 2.7.5 /version
relativePath/
/parent
groupId com.cjs.example /groupId
artifactId activiti7-sample /artifactId
version 0.0.1-SNAPSHOT /version
packaging pom /packaging
name activiti7-sample /name
modules
module activiti7-sample-provider-api /module
module activiti7-sample-provider /module
/modules
properties
java.version 17 /java.version
maven.compiler.source 17 /maven.compiler.source
maven.compiler.target 17 /maven.compiler.target
/properties
dependencies
dependency
groupId org.projectlombok /groupId
artifactId lombok /artifactId
optional true /optional
/dependency
/dependencies
dependencyManagement
dependencies
dependency
groupId org.activiti /groupId
artifactId activiti-spring-boot-starter /artifactId
version 7.1.0.M6 /version
/dependency
dependency
groupId org.activiti /groupId
artifactId activiti-dependencies /artifactId
version 7.6.1 /version
type pom /type
scope import /scope
/dependency
dependency
groupId org.apache.dubbo /groupId
artifactId dubbo-bom /artifactId
version 3.1.3 /version
type pom /type
scope import /scope
/dependency
dependency
groupId com.baomidou /groupId
artifactId mybatis-plus-boot-starter /artifactId
version 3.5.2 /version
/dependency
/dependencies
/dependencyManagement
repositories
repository
id activiti-releases /id
url https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases /url
/repository
/repositories
/project
4. Activiti API使用
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"
modelVersion 4.0.0 /modelVersion
parent
groupId com.cjs.example /groupId
artifactId activiti7-sample /artifactId
version 0.0.1-SNAPSHOT /version
/parent
groupId com.cjs.example /groupId
artifactId activiti7-sample-provider /artifactId
version ${parent.version} /version
name activiti7-sample-provider /name
properties
java.version 17 /java.version
/properties
dependencies
dependency
groupId com.cjs.example /groupId
artifactId activiti7-sample-provider-api /artifactId
version ${project.version} /version
/dependency
dependency
groupId org.apache.dubbo /groupId
artifactId dubbo /artifactId
/dependency
dependency
groupId org.apache.dubbo /groupId
artifactId dubbo-registry-nacos /artifactId
/dependency
dependency
groupId org.apache.dubbo /groupId
artifactId dubbo-spring-boot-starter /artifactId
/dependency
dependency
groupId org.activiti /groupId
artifactId activiti-spring-boot-starter /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-jdbc /artifactId
/dependency
dependency
groupId org.springframework.boot /groupId
artifactId spring-boot-starter-security /artifactId
/dependency
dependency
groupId com.baomidou /groupId
artifactId mybatis-plus-boot-starter /artifactId
/dependency
dependency
groupId com.mysql /groupId
artifactId mysql-connector-j /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
configuration
excludes
exclude
groupId org.projectlombok /groupId
artifactId lombok /artifactId
/exclude
/excludes
/configuration
/plugin
/plugins
/build
/project
application.yml
server:
port: 8080
servlet:
context-path: /activiti7
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/activiti7?useUnicode=true characterEncoding=utf8 allowMultiQueries=true nullCatalogMeansCurrent=true serverTimezone=Asia/Shanghai
username: root
password: 123456
activiti:
check-process-definitions: false
database-schema-update: "false" # 第一次运行时设置为true,待表生成完以后改成false,以后就不用再更新表结构了
db-history-used: true
history-level: full
deployment-mode: "never-fail" # org.activiti.spring.autodeployment.AbstractAutoDeploymentStrategy
dubbo:
application:
name: activiti7-sample-provider
protocol:
name: dubbo
port: -1
registry:
address: nacos://127.0.0.1:8848
config-center:
address: nacos://127.0.0.1:8848
metadata-report:
address: nacos://127.0.0.1:8848
启动项目后,生成的表结构如图:
也可以自己执行SQL脚本,脚本在源码包activiti-engine-7.6.1.jar里面
由于Activit7集成了SpringSecurity,它用SpringSecurity来做权限管理,因此它需要一个UserDetailsService,不配做的话启动会报错。当然网上也有一种解决办法就是排除SpringSecurity相关的某些类,没试过,应该也是可以的吧。
按照Spring Security 5.7以后的新写法,我们来配置一下WebSecurity
https://docs.spring.io/spring-security/reference/servlet/configuration/java.html
https://github.com/spring-projects/spring-security-samples/tree/6.0.x/servlet/spring-boot/java/oauth2
package com.cjs.example.provider.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
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.WebSecurityCustomizer;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
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.SecurityFilterChain;
* https://docs.spring.io/spring-security/reference/servlet/configuration/java.html
* https://github.com/spring-projects/spring-security-samples/tree/6.0.x/servlet/spring-boot/java/oauth2
* @Author: ChengJianSheng
* @Date: 2022/12/5
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(authorize - authorize.anyRequest().authenticated())
.formLogin(Customizer.withDefaults());
return http.build();
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) - web.ignoring()
// Spring Security should completely ignore URLs starting with /resources/
.antMatchers("/resources/**");
@Bean
public UserDetailsService userDetailsService() {
UserDetails admin = User.withUsername("tom")
.password("$2a$10$tk29HhXGXCZDOSvn.VZlFeBsLmtJrKE2Uv6zLrRpTyvZMu3ipQLgC")
.roles("ACTIVITI_USER", "ACTIVITI_ADMIN", "APPLICATION_MANAGER")
.build();
UserDetails user = User.withUsername("jerry")
.password("$2a$10$tk29HhXGXCZDOSvn.VZlFeBsLmtJrKE2Uv6zLrRpTyvZMu3ipQLgC")
.roles("ACTIVITI_USER", "GROUP_BUSINESS_MANAGER")
.build();
UserDetails zhangsan = User.withUsername("zhangsan")
.password("$2a$10$tk29HhXGXCZDOSvn.VZlFeBsLmtJrKE2Uv6zLrRpTyvZMu3ipQLgC")
.roles("ACTIVITI_USER")
.build();
UserDetails lisi = User.withUsername("lisi")
.password("$2a$10$tk29HhXGXCZDOSvn.VZlFeBsLmtJrKE2Uv6zLrRpTyvZMu3ipQLgC")
.roles("ACTIVITI_USER")
.build();
return new InMemoryUserDetailsManager(admin, user, zhangsan, lisi);
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
public static void main(String[] args) {
System.out.println(new BCryptPasswordEncoder().encode("123456"));
}
在activiti-spring-boot-starter中新提供了ProcessRuntime 和 TaskRuntime用于流程和任务处理的API,调用它们需要当前操作的用户具有ACTIVITI_USER权限
因此,在使用这两个类之前要保证当前登录用户有这个权限。为了模拟登录,我们来写个登录方法。
package com.cjs.example.provider.util;
import org.springframework.beans.factory.annotation.Autowired;
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;
* @Author: ChengJianSheng
* @Date: 2022/12/6
@Component
public class SecurityUtil {
@Autowired
private UserDetailsService userDetailsService;
public void logInAs(String username) {
UserDetails user = userDetailsService.loadUserByUsername(username);
if (null == user) {
throw new IllegalStateException(String.format("用户【%s】不存在", username));
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);
}
现在可以开始调用API操作流程了
package com.cjs.example.provider.service;
import com.cjs.example.provider.api.WorkflowService;
import com.cjs.example.provider.util.SecurityUtil;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.model.payloads.GetProcessInstancesPayload;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Order;
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.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
* @Author: ChengJianSheng
* @Date: 2022/12/6
@DubboService
public class WorkflowServiceImpl implements WorkflowService {
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private TaskRuntime taskRuntime;
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private SecurityUtil securityUtil;
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("processes/leave.bpmn20.xml")
.name("请假")
.key("leave")
.category("AAA")
.tenantId("QingJia")
.deploy();
@Override
public void start() {
securityUtil.logInAs("tom");
ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder.start()
.withProcessDefinitionKey("leave")
.withVariable("hello", "world")
.withVariable("apple", "orange")
.withBusinessKey("1")
.build());
@Override
public void startProcessInstance(String processDefinitionKey, String businessKey, Map String, Object variables, String tenantId) {
runtimeService.startProcessInstanceByKeyAndTenantId(processDefinitionKey, businessKey, variables, tenantId);
@Override
public void processInstancePage(int pageNo, int pageSize) {
securityUtil.logInAs("tom");
GetProcessInstancesPayload payload = new GetProcessInstancesPayload();
payload.setActiveOnly(true);
Page ProcessInstance page = processRuntime.processInstances(Pageable.of(pageNo-1, pageSize, Order.by("start_time_", Order.Direction.DESC)), payload);
for (ProcessInstance ps : page.getContent()) {
System.out.println(ps);
@Override
public void taskList() {
securityUtil.logInAs("zhangsan");
Page Task taskPage = taskRuntime.tasks(Pageable.of(0, 10));
System.out.println(taskPage.getTotalItems());
securityUtil.logInAs("lisi");
taskPage = taskRuntime.tasks(Pageable.of(0, 10));
System.out.println(taskPage.getTotalItems());
@Override
public void claimTask() {
securityUtil.logInAs("zhangsan");
String taskId = "429ad159-754c-11ed-aaf8-84a9386654d8";
Task task = taskRuntime.task(taskId);
taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(taskId).build());
@Override
public void completeTask() {
securityUtil.logInAs("zhangsan");
String taskId = "429ad159-754c-11ed-aaf8-84a9386654d8";
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).build());
}
注意:可以把tenantId看成是某个业务,businessKey当做业务ID,比如:放款流程001。或者建一张中间表用于关联流程ID和业务ID。
最后,配置流程监听器
package com.cjs.example.provider.config;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.process.runtime.events.ProcessCompletedEvent;
import org.activiti.api.process.runtime.events.listener.ProcessRuntimeEventListener;
import org.activiti.api.task.runtime.events.TaskAssignedEvent;
import org.activiti.api.task.runtime.events.TaskCompletedEvent;
import org.activiti.api.task.runtime.events.listener.TaskRuntimeEventListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
* @Author: ChengJianSheng
* @Date: 2022/12/6
@Slf4j
@Configuration
public class ListenerConfig {
@Bean
public ProcessRuntimeEventListener ProcessCompletedEvent processCompletedListener() {
return processCompleted - log.info(" Process Completed: "
+ processCompleted.getEntity().getName() +
" We can send a notification to the initiator: " + processCompleted.getEntity().getInitiator());
@Bean
public TaskRuntimeEventListener TaskAssignedEvent taskAssignedListener() {
return taskAssigned - log.info(" Task Assigned: "
+ taskAssigned.getEntity().getName() +
" We can send a notification to the assginee: " + taskAssigned.getEntity().getAssignee());
@Bean
public TaskRuntimeEventListener TaskCompletedEvent taskCompletedListener() {
return taskCompleted - log.info(" Task Completed: "
+ taskCompleted.getEntity().getName() +
" We can send a notification to the owner: " + taskCompleted.getEntity().getOwner());
}
代码:https://gitee.com/chengjiansheng/activiti7-sample
以上就是Activiti7+SpringBoot()的详细内容,想要了解更多 Activiti7+SpringBoot的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。