Activiti7整合Springboot使用記錄

0.Springboot項目創建

通過https://start.spring.io/生成純凈的一個springboot工程

1.引入Activiti相關依賴

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M6</version>
</dependency>

2.啟動工程並創建activiti數據庫

##activiti7中使用spring security,因此啟動工程前,需要加入2個文件支持,2個文件的代碼如下:

package cn.gzsendi.activitidemotest.config;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;

@Configuration
public class ActivitiConfiguration {
	
	private Logger logger = LoggerFactory.getLogger(ActivitiConfiguration.class);
	
	@Bean(name = "userDetailsService")
    public UserDetailsService myUserDetailsService() {

        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();

        //用戶
        String[][] usersGroupsAndRoles = {
                {"hefy", "123456", "ROLE_ACTIVITI_USER"},
                {"liujh", "123456", "ROLE_ACTIVITI_ADMIN"},
                {"liuky", "123456", "ROLE_ACTIVITI_USER"},
                {"admin", "123456", "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;

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

}
package cn.gzsendi.activitidemotest.utils;

import java.util.Collection;

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 javax.annotation.Resource;

@Component
public class SecurityUtil {
	
	@Autowired
    @Qualifier("userDetailsService")
    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);
    }

}

##加入activiti7的配置

server.port=8080
server.servlet.context-path=/activitidemotest

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/activitidemo?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=123456

spring.activiti.database-schema-update=true
spring.activiti.db-history-used=true
spring.activiti.history-level=full
spring.activiti.check-process-definitions=false
spring.activiti.deployment-mode=never-fail
spring.activiti.process-definition-location-prefix=classpath:/process/

##啟動springboot工程,讓系統啟動時幫我們建好25張表 2.安裝Activiti插件(設計器) ##Idea

file->settings->plugins,然後找actiBPM進行安裝。
在這裡插入圖片描述

##流程圖中亂碼問題先提前設置防止:

修改idea64.exe.vmoptions文件,在文件中加上如下,然後重啟Idea

-Dfile.encoding=utf-8

##進行流程設計

File->new->BpmnFile
在這裡插入圖片描述
在這裡插入圖片描述

設計好後,修改Process1.bpmn成Process1.xml,然後右鍵export file導出成Process1.jpg,再將Process1.bpmn修改成Process1.bpmn20.xml,最後將2個文件放在process文件夾
在這裡插入圖片描述

3.流程部署

使用activiti提供的api把流程定義內容存儲起來,Activiti執行把流程定義內容存儲在數據庫中。

package cn.gzsendi.activitidemotest;

/**
 * Created by jxlhl on 2021/8/18.
 */

import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
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;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootJunitTest {

    //得到RepositoryService實例
    @Autowired
    private RepositoryService repositoryService;

    //0.流程部署,單個文件部署方式
    @Test
    public void testDeployment(){

        //使用RepositoryService進行部署
        DeploymentBuilder builder = repositoryService.createDeployment();
        builder.addClasspathResource("process/Process1.bpmn20.xml");
        builder.addClasspathResource("process/Process1.jpg");
        builder.name("first_activiti_process");
        Deployment deployment = builder.deploy();

        //輸出部署信息
        System.out.println("流程部署id:" + deployment.getId());
        System.out.println("流程部署名稱:" + deployment.getName());

        //流程部署id:125098e1-ffd9-11eb-8847-02004c4f4f50
        //流程部署名稱:first_activiti_process

    }

}

執行此操作後activiti會將上邊代碼中指定的bpmn20文件和圖片文件保存在activiti數據庫。

流程定義部署後操作activiti的3張表

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

4.流程實例啟動

啟動一個流程實例表示開始一次業務流程的運行

  //1.流程實例啟動
    @Test
    public void testStartProcess(){
        //根據流程定義Id啟動流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_1");

        //輸出實例信息
        System.out.println("流程定義id:" + processInstance.getProcessDefinitionId());
        System.out.println("流程實例id:" + processInstance.getId());
        System.out.println("當前活動Id:" + processInstance.getActivityId());

        //流程定義id:myProcess_1:1:12702ed4-ffd9-11eb-8847-02004c4f4f50
        //流程實例id:a9b162aa-ffda-11eb-bad1-02004c4f4f50
        //當前活動Id:null

    }

流程實例啟動,將操作以下幾個數據庫表

act_hi_actinst 流程實例執行歷史
act_hi_identitylink 流程的參與用戶歷史信息
act_hi_procinst 流程實例歷史信息
act_hi_taskinst 流程任務歷史信息
act_ru_execution 流程執行信息
act_ru_identitylink 流程的參與用戶信息
act_ru_task 任務信息

5.任務查詢

流程啟動後,任務的負責人就可以查詢自己當前需要處理的任務,查詢出來的任務都是該用戶的待辦任務。

 //2.任務查詢
    //流程啟動後,任務的負責人就可以查詢自己當前需要處理的任務,查詢出來的任務都是該用戶的待辦任務。
    @Test
    public void testFindPersonalTaskList() {
        //任務負責人
        String assignee = "liuky";

        //根據流程key 和 任務負責人 查詢任務
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("myProcess_1")
                .taskAssignee(assignee)
                .list();

        for (Task task : list) {

            System.out.println("流程實例id:" + task.getProcessInstanceId());
            System.out.println("任務id:" + task.getId());
            System.out.println("任務負責人:" + task.getAssignee());
            System.out.println("任務名稱:" + task.getName());

        }

        //流程實例id:a9b162aa-ffda-11eb-bad1-02004c4f4f50
        //任務id:a9b5815e-ffda-11eb-bad1-02004c4f4f50
        //任務負責人:liuky
        //任務名稱:提交申請

    }

6. 完成任務

 @Test
    public void completTask(){

        //根據流程key和任務的負責人查詢任務並選擇其中的一個任務處理,這裡用的
        //是singleResult返回一條,真實環境中是通過步驟5中查詢出所有的任務,然後在頁面上選擇一個任務進行處理.
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myProcess_1") //流程Key
                .taskAssignee("liuky")  //要查詢的負責人
                .singleResult();
                
        //完成任務,參數:任務id
        taskService.complete(task.getId());

    }

7.流程結束,或流程流轉過程中的歷史信息查詢

   //流程結束,或流程流轉過程中的歷史信息查詢
    @Test
    public void findHistoryInfo(){

        //獲取 actinst表的查詢對象
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
        //查詢 actinst表,條件:根據 InstanceId 查詢
        instanceQuery.processInstanceId("fb5b7674-ffde-11eb-91f8-02004c4f4f50");
        //增加排序操作,orderByHistoricActivityInstanceStartTime 根據開始時間排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        //查詢所有內容
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
        //輸出結果
        for (HistoricActivityInstance hi : activityInstanceList) {

            System.out.println("");
            System.out.println("===================-===============");
            System.out.println(hi.getStartTime());
            System.out.println(hi.getAssignee());
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("===================-===============");
            System.out.println("");

        }
    }

8.其他Api測試

8.1 流程定義信息查詢

查詢流程相關信息,包含流程定義,流程部署,流程定義版本

@Test
    public void queryProcessDefinition(){

        //得到ProcessDefinitionQuery對象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

        //查詢出當前所有的流程定義
        List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("myProcess_1")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        //打印結果
        for (ProcessDefinition processDefinition : definitionList) {
            System.out.println("流程定義 id="+processDefinition.getId());
            System.out.println("流程定義 name="+processDefinition.getName());
            System.out.println("流程定義 key="+processDefinition.getKey());
            System.out.println("流程定義 Version="+processDefinition.getVersion());
            System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
        }

    }

8.2 刪除流程

  //刪除流程
    @Test
    public void deleteDeployment(){

        String deploymentId = "125098e1-ffd9-11eb-8847-02004c4f4f50";

        //刪除流程定義,如果該流程定義已有流程實例啟動則刪除時出錯
        repositoryService.deleteDeployment(deploymentId);

        //設置true 級聯刪除流程定義,即使該流程有流程實例啟動也可以刪除,設置為false非級別刪除方式,如果流程
        //repositoryService.deleteDeployment(deploymentId, true);

    }

9.demo源碼下載

github: https://github.com/jxlhljh/activitidemotest.git
gitee: https://gitee.com/jxlhljh/activitidemotest.git

到此這篇關於Activiti7整合Springboot使用記錄的文章就介紹到這瞭,更多相關Springboot整合Activiti7內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: