Activiti7+SpringBoot()

  本篇文章为你整理了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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: