Activiti7之整合spring和spring boot


整合spring

通過 org.activiti.spring.SpringProcessEngineConfiguration Spring 整合方式來創建ProcessEngine 對象。

1.導入依賴

jdk的版本是1.8

junit的版本必須是4.12以上

  1 <dependencies>
  2     <dependency>
  3       <groupId>org.activiti</groupId>
  4       <artifactId>activiti-engine</artifactId>
  5       <version>7.0.0.Beta1</version>
  6     </dependency>
  7 
  8     <dependency>
  9       <groupId>org.activiti</groupId>
 10       <artifactId>activiti-bpmn-model</artifactId>
 11       <version>7.0.0.Beta1</version>
 12     </dependency>
 13 
 14     <dependency>
 15       <groupId>org.activiti</groupId>
 16       <artifactId>activiti-bpmn-converter</artifactId>
 17       <version>7.0.0.Beta1</version>
 18     </dependency>
 19 
 20     <dependency>
 21       <groupId>org.activiti</groupId>
 22       <artifactId>activiti-json-converter</artifactId>
 23       <version>7.0.0.Beta1</version>
 24     </dependency>
 25 
 26  <!--   <dependency>
 27       <groupId>org.activiti</groupId>
 28       <artifactId>activiti-bpmn-layout</artifactId>
 29       <version>7.0.0.Beta1</version>
 30     </dependency>-->
 31 
 32     <dependency>
 33       <groupId>org.activiti.cloud</groupId>
 34       <artifactId>activiti-cloud-services-api</artifactId>
 35       <version>7.0.0.Beta1</version>
 36     </dependency>
 37 
 38     <!--activiti和Spring整合依賴-->
 39     <dependency>
 40       <groupId>org.activiti</groupId>
 41       <artifactId>activiti-spring</artifactId>
 42       <version>7.0.0.Beta1</version>
 43     </dependency>
 44 
 45     <!--數據庫依賴-->
 46     <dependency>
 47       <groupId>mysql</groupId>
 48       <artifactId>mysql-connector-java</artifactId>
 49       <version>5.1.38</version>
 50     </dependency>
 51 
 52 
 53     <!--單測依賴-->
 54     <dependency>
 55       <groupId>junit</groupId>
 56       <artifactId>junit</artifactId>
 57       <version>4.12</version>
 58     </dependency>
 59 
 60     <dependency>
 61       <groupId>org.springframework</groupId>
 62       <artifactId>spring-test</artifactId>
 63       <version>5.0.7.RELEASE</version>
 64     </dependency>
 65 
 66 
 67     <!-- log start -->
 68     <dependency>
 69       <groupId>log4j</groupId>
 70       <artifactId>log4j</artifactId>
 71       <version>${log4j.version}</version>
 72     </dependency>
 73     <dependency>
 74       <groupId>org.slf4j</groupId>
 75       <artifactId>slf4j-api</artifactId>
 76       <version>${slf4j.version}</version>
 77     </dependency>
 78     <dependency>
 79       <groupId>org.slf4j</groupId>
 80       <artifactId>slf4j-log4j12</artifactId>
 81       <version>${slf4j.version}</version>
 82     </dependency>
 83 
 84 
 85     <dependency>
 86       <groupId>org.mybatis</groupId>
 87       <artifactId>mybatis</artifactId>
 88       <version>3.4.5</version>
 89     </dependency>
 90 
 91 
 92     <!--數據源-->
 93     <dependency>
 94       <groupId>commons-dbcp</groupId>
 95       <artifactId>commons-dbcp</artifactId>
 96       <version>1.4</version>
 97     </dependency>
 98 
 99     <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
100     <dependency>
101       <groupId>commons-io</groupId>
102       <artifactId>commons-io</artifactId>
103       <version>2.4</version>
104     </dependency>
105 
106   </dependencies>
107   <repositories>
108     <repository>
109       <id>alfresco</id>
110       <name>Activiti Releases</name>
111       <url>https://artifacts.alfresco.com/nexus/content/repositories/activiti-releases/</url>
112       <releases>
113         <enabled>true</enabled>
114       </releases>
115     </repository>
116   </repositories>
依賴

 

2.配置Activiti

 1 配置內容:1.數據源         2.配置processEngine對象        3.配置XXXXService
 2                 <!--數據源-->
 3                 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
 4                     <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
 5                     <property name="url" value="jdbc:mysql://localhost:3306/activiti-y2170"/>
 6                     <property name="username" value="root"/>
 7                     <property name="password" value="root"/>
 8                 </bean>
 9 
10                 <!--配置ProcessEngineConfiguration-->
11                 <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
12                     <!--數據源-->
13                     <property name="dataSource" ref="dataSource"/>
14                     <!--配置事務-->
15                     <property name="transactionManager" ref="transactionManager"/>
16                     <!--數據生成策略    true   false   create   drop-create -->
17                     <property name="databaseSchemaUpdate" value="true"/>
18                 </bean>
19 
20                 <!--配置ProcessEngine-->
21                 <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
22                     <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
23                 </bean>
24 
25                 <!--配置RepositoryService-->
26                 <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
27                 <!--配置RuntimeService-->
28                 <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
29                 <!--配置TaskService-->
30                 <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
31                 <!--配置HistoryService-->
32                 <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
33                 
34                 <!--配置事務管理器-->
35                 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
36                     <property name="dataSource" ref="dataSource"/>
37                 </bean>
配置

 

3.測試

 1 package com.wish;
 2 
 3 import static org.junit.Assert.assertTrue;
 4 
 5 import org.activiti.engine.RepositoryService;
 6 import org.junit.Test;
 7 import org.junit.runner.RunWith;
 8 import org.springframework.test.context.ContextConfiguration;
 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 
11 import javax.annotation.Resource;
12 
13 /**
14  * Unit test for simple App.
15  */
16 @RunWith(SpringJUnit4ClassRunner.class)     //測試方式  junit4.12+
17 @ContextConfiguration("classpath:springActibiti.xml")   //配置
18 public class AppTest 
19 {
20     @Resource
21     private RepositoryService repositoryService;
22     @Test
23     public void shouldAnswerWithTrue()
24     {
25         System.out.println("部署對象:"+repositoryService);
26     }
27 }
測試

 

運行結果:接下來就可以部署了

 

 

 

使用RepositoryService 進行部署

 1    /**
 2      * 測試流程部署
 3      */
 4     @Test
 5     public void deployment(){
 6         repositoryService.createDeployment()
 7                 .addClasspathResource("flowchart/process.bpmn")
 8                 .name("測試Spring流程部署")
 9                 .deploy();
10     }
repositoryService部署

 

運行結果

 

 

 

 

 

 

執行流程分析

下面我們一起來分析Activiti 與Spring 整合加載的過程。如下圖所示:

從圖中我們可以看出,首先我們加載 activiti-spring.xml 配置文件,而該配置文件中又會加載SpringProcessEngineConfiguration 對 象 ,

這 個 對 象 它 需 要 依 賴 注 入 dataSource 對 象 和transactionManager 對象。

其次會加載ProcessEngineFactoryBean 工廠來創建ProcessEngine 對象,而ProcessEngineFactoryBean 工廠又需要 依賴注 入 processEngineConfiguration 對 象。

最后 由processEngine 對象來負責創建我們的 Service 對象,從而簡化 Activiti 的開發過程。在程序代碼中我們可以根據實際需求來決定使用的Service 對象。

 

Activiti7的新特性

Activiti7的GitHub官方網站:https://github.com/Activiti/activiti-7-developers-guide/blob/51a1681c0e4bb5e2f96a6dea73516c9fd53 d8521/getting-started/getting-started-activiti-core.md

 

下載 Activiti-Core 的Example 示例:https://github.com/Activiti/activiti-examples

 

Activiti7 為了簡化對工作流的操作,特別在原有 API 的基礎上再次進行封閉,這樣我們原來所學習的Activiti 基本API 就被封閉起來了。

具體要學習的包括:

ProcessRuntime 接口TaskRuntime 接口

ProcessRuntime 接口

 

通過上面的分析,我們發現使用 Activiti7 開發時,只要注入ProcessRuntime 的實現對象,就可以實現流程定義信息的操作。

當然這個過程中因為 Activiti7 與SpringSecurity 的強耦合,引導我們也必須將SpringSecurity 加入進來。

 

TaskRuntime 接口

 

 

 

 

上面部分給我們介紹了如何引入Activiti Core 所需的坐標,同時介紹了如何添加 TaskRuntime 實現對象,源碼介紹等。我們會發現TaskRuntime 本身就是對於TaskService 的一個封裝。

SpringBoot整合Activiti7

 導入依賴

 1    <parent>
 2         <groupId>org.springframework.boot</groupId>
 3         <artifactId>spring-boot-starter-parent</artifactId>
 4         <version>2.1.4.RELEASE</version>
 5     </parent>
 6 
 7 
 8 <dependency>
 9             <groupId>org.springframework.boot</groupId>
10             <artifactId>spring-boot-starter-jdbc</artifactId>
11         </dependency>
12         <dependency>
13             <groupId>org.springframework.boot</groupId>
14             <artifactId>spring-boot-starter-web</artifactId>
15         </dependency>
16         <dependency>
17             <groupId>org.springframework.boot</groupId>
18             <artifactId>spring-boot-starter-test</artifactId>
19             <scope>test</scope>
20         </dependency>
21         <!-- https://mvnrepository.com/artifact/org.activiti/activiti-spring-boot-starter -->
22         <dependency>
23             <groupId>org.activiti</groupId>
24             <artifactId>activiti-spring-boot-starter</artifactId>
25             <version>7.0.0.Beta2</version>
26         </dependency>
27         <dependency>
28             <groupId>org.mybatis</groupId>
29             <artifactId>mybatis</artifactId>
30             <version>3.4.5</version>
31         </dependency>
32         <dependency>
33             <groupId>mysql</groupId>
34             <artifactId>mysql-connector-java</artifactId>
35             <version>5.1.38</version>
36         </dependency>
依賴

 

配置application.yml

1 spring:
2   datasource:
3     url: jdbc:mysql://localhost:3306/activiti-wn?useUnicode=true&characterEncoding=utf8&serverT imezone=GMT
4     username : root
5     password : 123456
6     driver-class-name: com.mysql.jdbc.Driver
7   activiti:
8     db-history-used: true   #開啟歷史信息
配置application.yml

 

將SpringSecurity配置添加到項目當中

SecurityUtil關於權限登陸

 1 package com.wish.activiti;
 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 java.util.Collection;
13 
14 @Component
15 public class SecurityUtil {
16 
17     @Autowired
18     private UserDetailsService userDetailsService;
19 
20     public void logInAs(String username) {
21 
22          UserDetails user = userDetailsService.loadUserByUsername(username);
23         if (user == null) {
24             throw new IllegalStateException("User " + username + " doesn't exist, please provide a valid user");
25         }
26 
27         SecurityContextHolder.setContext(new SecurityContextImpl(new Authentication() {
28             @Override
29             public Collection<? extends GrantedAuthority> getAuthorities() {
30                 return user.getAuthorities();
31             }
32 
33             @Override
34             public Object getCredentials() {
35                 return user.getPassword();
36             }
37 
38             @Override
39             public Object getDetails() {
40                 return user;
41             }
42 
43             @Override
44             public Object getPrincipal() {
45                 return user;
46             }
47 
48             @Override
49             public boolean isAuthenticated() {
50                 return true;
51             }
52 
53             @Override
54             public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
55 
56             }
57 
58             @Override
59             public String getName() {
60                 return user.getUsername();
61             }
62         }));
63         org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
64     }
65 }
SecurityUtil

 

DemoApplicationConfiguration 關於權限配置

 1 /*
 2  * Copyright 2018 Alfresco, Inc. and/or its affiliates.
 3  *
 4  * Licensed under the Apache License, Version 2.0 (the "License");
 5  * you may not use this file except in compliance with the License.
 6  * You may obtain a copy of the License at
 7  *
 8  *       http://www.apache.org/licenses/LICENSE-2.0
 9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.wish.activiti;
18 
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.context.annotation.Bean;
23 import org.springframework.context.annotation.Configuration;
24 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
25 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
26 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
27 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
28 import org.springframework.security.core.authority.SimpleGrantedAuthority;
29 import org.springframework.security.core.userdetails.User;
30 import org.springframework.security.core.userdetails.UserDetailsService;
31 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
32 import org.springframework.security.crypto.password.PasswordEncoder;
33 import org.springframework.security.provisioning.InMemoryUserDetailsManager;
34 import java.util.Arrays;
35 import java.util.List;
36 import java.util.stream.Collectors;
37 
38 @Configuration
39 @EnableWebSecurity
40 public class DemoApplicationConfiguration extends WebSecurityConfigurerAdapter {
41 
42     private Logger logger = LoggerFactory.getLogger(DemoApplicationConfiguration.class);
43 
44     @Override
45     @Autowired
46     public void configure(AuthenticationManagerBuilder auth) throws Exception {
47         auth.userDetailsService(myUserDetailsService());
48     }
49 
50     @Bean
51     public UserDetailsService myUserDetailsService() {
52 
53         InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
54 
55         String[][] usersGroupsAndRoles = {
56                 {"salaboy", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
57                 {"ryandawsonuk", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
58                 {"erdemedeiros", "password", "ROLE_ACTIVITI_USER", "GROUP_activitiTeam"},
59                 {"other", "password", "ROLE_ACTIVITI_USER", "GROUP_otherTeam"},
60                 {"admin", "password", "ROLE_ACTIVITI_ADMIN"},
61         };
62 
63         for (String[] user : usersGroupsAndRoles) {
64             List<String> authoritiesStrings = Arrays.asList(Arrays.copyOfRange(user, 2, user.length));
65             logger.info("> Registering new user: " + user[0] + " with the following Authorities[" + authoritiesStrings + "]");
66             inMemoryUserDetailsManager.createUser(new User(user[0], passwordEncoder().encode(user[1]),
67                     authoritiesStrings.stream().map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList())));
68         }
69 
70 
71         return inMemoryUserDetailsManager;
72     }
73 
74 
75     @Override
76     protected void configure(HttpSecurity http) throws Exception {
77         http
78                 .csrf().disable()
79                 .authorizeRequests()
80                 .anyRequest()
81                 .authenticated()
82                 .and()
83                 .httpBasic();
84 
85 
86     }
87 
88     @Bean
89     public PasswordEncoder passwordEncoder() {
90         return new BCryptPasswordEncoder();
91     }
92 }
DemoApplicationConfiguration

 

啟動工程

 1 package com.wish;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 
 6 @SpringBootApplication
 7 public class StartActiviti {
 8     public static void main(String[] args) {
 9         SpringApplication.run(StartActiviti.class,args);
10     }
11 }
啟動項目

 

運行成功,數據庫創建表

 

 

注意問題:
1.Activiti7和SpringSecurity耦合,需要加入SpringSecurity的依賴和配置,我們可以使用Security中的用戶角色組定義流程執行的組
2.流程默認可自動部署,但是需要再resources/processes文件夾,將流程文件放入當中
3.默認歷史表不會生成,需要手動開啟配置

 

執行流程

 1 package com.wish.controller;
 2 
 3 
 4 import com.wish.activiti.SecurityUtil;
 5 import org.activiti.api.process.model.ProcessDefinition;
 6 import org.activiti.api.process.model.ProcessInstance;
 7 import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
 8 import org.activiti.api.process.runtime.ProcessRuntime;
 9 import org.activiti.api.runtime.shared.query.Page;
10 import org.activiti.api.runtime.shared.query.Pageable;
11 import org.activiti.api.task.model.Task;
12 import org.activiti.api.task.model.builders.TaskPayloadBuilder;
13 import org.activiti.api.task.runtime.TaskRuntime;
14 import org.springframework.web.bind.annotation.RequestMapping;
15 import org.springframework.web.bind.annotation.RestController;
16 
17 import javax.annotation.Resource;
18 
19 @RestController
20 @RequestMapping("/activiti")
21 public class ActivitiController {
22     @Resource
23     private ProcessRuntime processRuntime;
24     @Resource
25     private TaskRuntime taskRuntime;
26     @Resource
27     private SecurityUtil securityUtil;
28     /**
29      * 查詢流程定義
30      */
31     @RequestMapping("/getProcess")
32     public void getProcess(){
33         //查詢所有流程定義信息
34         Page<ProcessDefinition> processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
35         System.out.println("當前流程定義的數量:"+processDefinitionPage.getTotalItems());
36         //獲取流程信息
37         for (ProcessDefinition processDefinition:processDefinitionPage.getContent()) {
38             System.out.println("流程定義信息"+processDefinition);
39         }
40     }
41 
42     /**
43      * 啟動流程示例
44      */
45     @RequestMapping("/startInstance")
46     public void startInstance(){
47         ProcessInstance instance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("demo").build());
48         System.out.println(instance.getId());
49     }
50 
51     /**
52      * 獲取任務,拾取任務,並且執行
53      */
54     @RequestMapping("/getTask")
55     public void getTask(){
56         securityUtil.logInAs("salaboy");        //指定組內任務人
57         Page<Task> tasks = taskRuntime.tasks(Pageable.of(0, 10));
58         if(tasks.getTotalItems()>0){
59             for (Task task:tasks.getContent()) {
60                 System.out.println("任務名稱:"+task.getName());
61                 //拾取任務
62                 taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
63                 //執行任務
64                 taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId()).build());
65             }
66         }
67     }
68 }
執行流程

 

執行查詢流程定義操作

 

 

 

 

執行啟動流程示例

 

 

 

 

 

 

執行獲取任務,拾取任務,並且執行操作

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM