springboot2整合activiti7具体步骤

写在前面

需要提前了解的内容有 springboot、springSecurity、activiti基本使用

关于activiti

Activiti项目是一项新的基于Apache许可的开源BPM平台,从基础开始构建,旨在提供支持新的BPMN 2.0标准,包括支持对象管理组(OMG),面对新技术的机遇,诸如互操作性和云架构,提供技术实现。

activiti主要应用场景

需要动态地改变流程的业务流程场景。例如请假流程、项目审批流程等。

正题

第一步:

新建一个springboot项目,引入activiti-spring-boot-starter和你所使用的数据库驱动器。本文采用Mysql 8.

读者也可以直接复制下面的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>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>pers.lbf</groupId>
<artifactId>springboot-activiti</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-activiti</name>
<description>Demo project for Spring Boot</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.12</version>
</dependency>

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>


<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.0.0.Beta2</version>
</dependency>


</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>


第二步,修改application.yml配置文件

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/你的数据库?userSSL=false&serverTimezone=GMT%2B8
    username: root
    password: 你的密码
    driver-class-name: com.mysql.cj.jdbc.Driver
 

activiti:

database-schema-update: true
    db-history-used: true
    history-level: audit

第三步,添加springSecurity的相关配置。

因为activiti7与springboot整合之后,默认情况下集成了springSecurity框架,所以我们需要配置一下springSecurity。本文的核心不在springSecurity,所以这一步将通过添加一个工具类的方式来完成。

 1 package pers.lbf.springbootactiviti.utils;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.security.core.Authentication;
 5 import org.springframework.security.core.GrantedAuthority;
 6 import org.springframework.security.core.context.SecurityContextHolder;
 7 import org.springframework.security.core.context.SecurityContextImpl;
 8 import org.springframework.security.core.userdetails.UserDetails;
 9 import org.springframework.security.core.userdetails.UserDetailsService;
10 import org.springframework.stereotype.Component;
11 
12 import javax.security.auth.Subject;
13 import javax.vecmath.Tuple2d;
14 import java.util.Collection;
15 
16 /**
17  * @author 赖柄沣 bingfengdev@aliyun.com
18  * @date 2020-08-18 11:27:31
19  * @version 1.0
20  */
21 @Component
22 public class SecurityUtil {
23 
24     @Autowired
25     private UserDetailsService userDetailsService;
26 
27     
28 
29     public void logInAs(String username) {
30 
31         UserDetails user = userDetailsService.loadUserByUsername(username);
32         if (user == null) {
33             throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
34         }
35 
36         Authentication authentication = new Authentication() {
37            
38             @Override
39             public String getName() {
40                 
41                 return user.getUsername();
42             }
43 
44             @Override
45             public boolean implies(Subject subject) {
46                 return false;
47             }
48 
49             @Override
50             public Collection<? extends GrantedAuthority> getAuthorities() {
51                 return user.getAuthorities();
52             }
53 
54             @Override
55             public Object getCredentials()
56             {
57                 return user.getPassword();
58             }
59 
60             @Override
61             public Object getDetails() {
62                 
63                 return user;
64             }
65 
66             @Override
67             public Object getPrincipal() {
68                 
69                 return user;
70             }
71 
72             @Override
73             public boolean isAuthenticated() {
74                 return true;
75             }
76 
77             @Override
78             public void setAuthenticated(boolean b) throws IllegalArgumentException {
79 
80             }
81         };
82 
83         SecurityContextImpl securityContext = new SecurityContextImpl();
84         securityContext.setAuthentication(authentication);
85         SecurityContextHolder.setContext(securityContext);
86         org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
87     }
88 }

第四步,添加权限配置信息。

正常项目中,权限信息存储于数据库当中。本文为了陈述方便,直接将权限信息定义在配置类当中。

package pers.lbf.springbootactiviti.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

/**
 * @author 赖柄沣 bingfengdev@aliyun.com
 * @version 1.0
 * @date 2020/8/18 11:40
 */
@Configuration
public class ApplicationConfig {

    @Bean
    public UserDetailsService getUserDetailsService(){

        InMemoryUserDetailsManager userDetailsManager = 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"},
                {"system", "password", "ROLE_ACTIVITI_USER"},
                {"admin", "password", "ROLE_ACTIVITI_ADMIN"}
        };

        for (String[] user : usersGroupsAndRoles) {
            List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user,2,user.length));

            userDetailsManager.createUser(new User(
                        user[0],
                        passwordEncoder().encode(user[1]),
                        authoritiesStrings.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList())
                    )
            );

        }

        return userDetailsManager;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

第五步,整合Junit,验证是否整合成功

首先,添加Junit依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>    

编写测试类

  1 package pers.lbf.springbootactiviti.activititest;
  2 
  3 import org.activiti.api.process.model.ProcessDefinition;
  4 import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
  5 import org.activiti.api.process.model.payloads.StartProcessPayload;
  6 import org.activiti.api.process.runtime.ProcessRuntime;
  7 import org.activiti.api.runtime.shared.query.Page;
  8 import org.activiti.api.runtime.shared.query.Pageable;
  9 import org.activiti.api.task.model.Task;
 10 import org.activiti.api.task.model.builders.ClaimTaskPayloadBuilder;
 11 import org.activiti.api.task.model.builders.CompleteTaskPayloadBuilder;
 12 import org.activiti.api.task.runtime.TaskRuntime;
 13 import org.activiti.engine.ProcessEngine;
 14 import org.activiti.engine.RepositoryService;
 15 import org.activiti.engine.repository.Deployment;
 16 import org.junit.Before;
 17 import org.junit.Test;
 18 import org.junit.runner.RunWith;
 19 import org.springframework.beans.factory.annotation.Autowired;
 20 import org.springframework.boot.test.context.SpringBootTest;
 21 import org.springframework.test.context.junit4.SpringRunner;
 22 import pers.lbf.springbootactiviti.utils.SecurityUtil;
 23 
 24 import java.util.List;
 25 
 26 /**
 27  * @author 赖柄沣 bingfengdev@aliyun.com
 28  * @version 1.0
 29  * @date 2020/8/18 12:10
 30  */
 31 @RunWith(SpringRunner.class)
 32 @SpringBootTest
 33 public class Activiti7SpringbootTest {
 34 
 35     @Autowired
 36     private ProcessRuntime processRuntime;
 37     @Autowired
 38     private TaskRuntime taskRuntime;
 39 
 40     @Autowired
 41     private SecurityUtil securityUtil;
 42 
 43     @Autowired
 44     private ProcessEngine processEngine;
 45 
 46     @Before
 47     public void init() {
 48         //认证
 49         securityUtil.logInAs("system");
 50     }
 51 
 52     /**部署流程
      说明:关于流程的部署,activiti7与springboot整合后,会自动部署已经创建好的流程文件(bpmn、png)
      只要将流程定义文件存放在"resources/processes/下即可"
53 * @author 赖柄沣 bingfengdev@aliyun.com 54 * @date 2020-08-18 12:53:51 55 * @version 1.0 56 */ 57 @Test 58 public void repositoryProcess(){ 59 RepositoryService repositoryService = processEngine.getRepositoryService(); 60 Deployment deployment = repositoryService.createDeployment() 61 .addClasspathResource("holiday.bpmn") 62 .name("请假流程") 63 .deploy(); 64 System.out.println(deployment.getName()); 65 System.out.println(deployment.getDeploymentTime()); 66 } 67 68 /**分页查询系统中所有可用的流程定义 69 * @author 赖柄沣 bingfengdev@aliyun.com 70 * @date 2020-08-18 13:32:36 71 * @version 1.0 72 */ 73 @Test 74 public void findProcessList(){ 75 Page<ProcessDefinition> processDefinitionPage = processRuntime 76 .processDefinitions(Pageable.of(0, 10)); 77 List<ProcessDefinition> content = processDefinitionPage.getContent(); 78 for (ProcessDefinition processDefinition : content) { 79 System.out.println(processDefinition.getName()); 80 } 81 } 82 83 /**启动流程 84 * @author 赖柄沣 bingfengdev@aliyun.com 85 * @date 2020-08-18 13:21:12 86 * @version 1.0 87 */ 88 @Test 89 public void startProcess(){ 90 91 StartProcessPayload myProcess = ProcessPayloadBuilder 92 .start() 93 .withProcessDefinitionId("myProcess_1:1:5c5e0de3-e112-11ea-a73b-287fcf13e373") 94 .build(); 95 96 myProcess.setProcessInstanceName("张三请假"); 97 processRuntime.start(myProcess); 98 System.out.println("流程实例"+myProcess.getId()); 99 100 } 101 102 /**查询并完成任务 103 * @author 赖柄沣 bingfengdev@aliyun.com 104 * @date 2020-08-18 13:41:40 105 * @version 1.0 106 */ 107 @Test 108 public void findAndFinishTask() { 109 Page<Task> taskPage = taskRuntime.tasks(Pageable.of(0, 10)); 110 111 if (taskPage.getTotalItems()>0){ 112 113 List<Task> content = taskPage.getContent(); 114 for (Task task : content) { 115 //拾取任务 116 taskRuntime.claim(new ClaimTaskPayloadBuilder() 117 .withTaskId(task.getId()) 118 .build()); 119 //完成任务 120 taskRuntime.complete(new CompleteTaskPayloadBuilder() 121 .withTaskId(task.getId()) 122 .build()); 123 } 124 } 125 126 } 127 128 }

 

End

本文仅介绍如何将activiti7集成到springboot中.具体的activiti使用请参考其他博文。

本文代码github地址:https://github.com/code81192/art-demo/tree/master/springboot-activiti7

 

posted @ 2020-08-18 14:10  __Ferryman  阅读(1929)  评论(1编辑  收藏  举报