欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot整合Activiti操作詳解

 更新時(shí)間:2023年07月06日 09:33:33   作者:啊幾  
這篇文章主要給大家詳細(xì)介紹了Springboot整合Activiti的操作流程,文中流程步驟和代碼示例介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下

版本依賴(lài)

  • 開(kāi)發(fā)工具 IDEA
  • SpringBoot 2.4.5(這里我試過(guò)SpringBoot 3.1.1版本,Activiti沒(méi)有啟動(dòng),應(yīng)該是依賴(lài)沖突了,后改成了2.4.5版本)
  • Activiti 7.1.0.M6

父項(xiàng)目pom.xml

    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.4.5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.activiti.dependencies/activiti-dependencies -->
            <dependency>
                <groupId>org.activiti.dependencies</groupId>
                <artifactId>activiti-dependencies</artifactId>
                <version>7.1.0.M6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

子項(xiàng)目pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>

配置文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    username: root
    password: 111111
    url: jdbc:mysql://127.0.0.1:3306/activiti?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false&useInformationSchema=true
    hikari:
      #連接池做大連接數(shù)
      maximum-pool-size: 30
      #連接池空閑連接最小數(shù)量
      #minimum-idle: 10
      #允許連接在連接池中閑置最長(zhǎng)時(shí)間
      #idle-timeout: 30000
      #池中連接最長(zhǎng)生命周期
      max-lifetime: 120000
      #等待來(lái)自池的連接的最大毫秒數(shù)
      connection-timeout: 30000
  activiti:
    #自動(dòng)更新數(shù)據(jù)庫(kù)結(jié)構(gòu)
    #1.flase:默認(rèn)值。activiti在啟動(dòng)時(shí),對(duì)比數(shù)據(jù)庫(kù)表中保存的版本,如果沒(méi)有表或者版本不匹配,將拋出異常
    #2.true: activiti會(huì)對(duì)數(shù)據(jù)庫(kù)中所有表進(jìn)行更新操作。如果表不存在,則自動(dòng)創(chuàng)建
    #3.create_drop: 在activiti啟動(dòng)時(shí)創(chuàng)建表,在關(guān)閉時(shí)刪除表(必須手動(dòng)關(guān)閉引擎,才能刪除表)
    #4.drop-create: 在activiti啟動(dòng)時(shí)刪除原來(lái)的舊表,然后在創(chuàng)建新表(不需要手動(dòng)關(guān)閉引擎)
    database-schema-update: true
    #activiti7默認(rèn)不生成歷史信息表,開(kāi)啟歷史表
    db-history-used: true
    #記錄歷史等級(jí) 可配置的歷史級(jí)別有none, activity, audit, full
    #none:不保存任何的歷史數(shù)據(jù),因此,在流程執(zhí)行過(guò)程中,這是最高效的。
    #activity:級(jí)別高于none,保存流程實(shí)例與流程行為,其他數(shù)據(jù)不保存。
    #audit:除activity級(jí)別會(huì)保存的數(shù)據(jù)外,還會(huì)保存全部的流程任務(wù)及其屬性。audit為history的默認(rèn)值。
    #full:保存歷史數(shù)據(jù)的最高級(jí)別,除了會(huì)保存audit級(jí)別的數(shù)據(jù)外,還會(huì)保存其他全部流程相關(guān)的細(xì)節(jié)數(shù)據(jù),包括一些流程參數(shù)等。
    history-level: full
    #自動(dòng)檢查、部署流程定義文件
    check-process-definitions: false
    # asyncExecutorActivate是指activiti在流程引擎啟動(dòng)就激活A(yù)syncExecutor,異步:true-開(kāi)啟(默認(rèn))、false-關(guān)閉
    async-executor-activate: true

配置文件這里注意要設(shè)置 database-sechema-update的屬性為true,才會(huì)自動(dòng)創(chuàng)建表。

需要注意的問(wèn)題

在初次啟動(dòng)時(shí)可能會(huì)報(bào)錯(cuò),報(bào)錯(cuò)如下:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.core.userdetails.UserDetailsService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
	... 142 more

這里是需要一個(gè)UserDetailsService的Bean,需要?jiǎng)?chuàng)建一個(gè)類(lèi)去實(shí)現(xiàn)UserDetailsService接口

UserDetailsServiceImpl.class

package org.example.config;
import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    UserService userService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userService.findOneUserByName(username);
    }
}

UserService.class

package org.example.service;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
    public User findOneUserByName(String username){
        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
        return new User(username,"",authorities);
    }
}

啟動(dòng)成功后,數(shù)據(jù)庫(kù)會(huì)生成25張表

在這里插入圖片描述

畫(huà)流程圖

在使用IDEA時(shí),需要下載一個(gè)插件

在這里插入圖片描述

當(dāng)這個(gè)插件安裝好以后,新建文件會(huì)多一個(gè)選項(xiàng)

在這里插入圖片描述

新建的xml文件可以通過(guò)view BPMN Diagram,轉(zhuǎn)化為圖表操作

在這里插入圖片描述

在這里插入圖片描述

如何通過(guò)圖表操作畫(huà)流程這里就不說(shuō)了,可以自己摸索看看。

activiti服務(wù)類(lèi)進(jìn)行編寫(xiě)

package org.example.service;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
@Service
public class ActivitiService {
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    RuntimeService runtimeService;
    @Autowired
    TaskService taskService;
    @Autowired
    HistoryService historyService;
    /**
     * 部署流程服務(wù)
     */
    public void deployProcess(){
        String file = "bpmn/test.bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource(file)
                .name("流程部署測(cè)試")
                .deploy();
        System.out.println("流程部署名稱(chēng):"+deployment.getName());
    }
    /**
     * 查詢(xún)所有部署的流程定義
     * @return
     */
    public List<ProcessDefinition> getAllProcessDefinition(){
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
        return query.orderByProcessDefinitionVersion().desc().list();
    }
    /**
     * 查詢(xún)所有的部署
     * @return
     */
    public List<Deployment> getAllDeployment(){
        DeploymentQuery query = repositoryService.createDeploymentQuery();
        return query.list();
    }
    /**
     * 查詢(xún)所有流程實(shí)例
     * @return
     */
    public List<ProcessInstance> getAllProcessInstance(){
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
        return list;
    }
    public List<Task> getAllProcessTask(){
        List<Task> list = taskService.createTaskQuery().list();
        return list;
    }
    /**
     * 查詢(xún)用戶(hù)待完成和待認(rèn)領(lǐng)的任務(wù)
     * @param username
     * @return
     */
    public List<Task> getAllProcessTaskByCandidateOrAssigned(String username){
        List<Task> list = taskService.createTaskQuery().taskCandidateOrAssigned(username).list();
        return list;
    }
    public List<Task> getAllProcessTaskByCandidate(String username){
        List<Task> list = taskService.createTaskQuery().taskCandidateUser(username).list();
        return list;
    }
    /**
     * 查詢(xún)用戶(hù)的待完成任務(wù)
     * @param username
     * @return
     */
    public List<Task> getAllProcessTaskByAssigned(String username){
        List<Task> list = taskService.createTaskQuery().taskAssignee(username).list();
        return list;
    }
    public void complateTask(Task task, Map<String, Object> map){
        taskService.complete(task.getId(),map);
    }
    public void complateTask(Task task){
        taskService.complete(task.getId());
    }
    public void claimTask(Task task,String username){
        taskService.claim(task.getId(),username);
    }
    public ProcessInstance startProcess(String processDefinitionKey,String businessKey,Map<String,Object> map){
        return runtimeService.startProcessInstanceById(processDefinitionKey,businessKey,map);
    }
    public String getProcessDefinitionXml(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId);
        String resourceName = processDefinition.getResourceName();
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        try {
            return IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8);
        } catch (IOException e) {
            // handle exception
        }
        return null;
    }
    public List<HistoricProcessInstance> getHistoryByBusinessKey(String businessKey){
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).list();
        return list;
    }
}

在這里插入圖片描述

上圖是,如果需要使用activiti中提供的服務(wù)類(lèi),直接注入即可。即springboot整合activiti啟動(dòng)過(guò)程中,已經(jīng)在容器中自動(dòng)裝配了對(duì)應(yīng)的服務(wù)類(lèi),需要的時(shí)候,僅僅需要取來(lái)用即可。如果啟動(dòng)以后報(bào)錯(cuò),容器沒(méi)有自動(dòng)裝配對(duì)應(yīng)的服務(wù)類(lèi),那很有可能是依賴(lài)沖突,activiti沒(méi)有正常啟動(dòng)。

流程部署

流程部署有多種方式,這是通過(guò)資源路徑部署的,也可以通過(guò)壓縮包的形式部署流程。那就需要用到DeploymentBuilderaddZipInputStream方法,這里也是用到了設(shè)計(jì)模式中的建造者模式。

在這里插入圖片描述

在這里插入圖片描述

流程定義

這是一個(gè)查詢(xún)所有部署的流程定義的方法

在這里插入圖片描述

當(dāng)一個(gè)流程部署以后,就會(huì)生成一個(gè)流程定義,流程圖的xml信息也會(huì)存入數(shù)據(jù)庫(kù)。每次部署流程圖都會(huì)生成一個(gè)新的流程定義。

在這里插入圖片描述

啟動(dòng)流程

啟動(dòng)流程可以通過(guò)流程定義的id或者key,如果想通過(guò)流程定義的id啟動(dòng)一個(gè)流程可以使用startProcessInstanceById方法,如果想通過(guò)流程定義的key啟動(dòng)一個(gè)流程可以使用startProcessInstanceByKey方法。

在這里插入圖片描述

這里要明白流程定義id和key的區(qū)別,流程定義的key是在畫(huà)流程的時(shí)候可以設(shè)置的,通過(guò)設(shè)置流程的id,這個(gè)就是流程的key。

在這里插入圖片描述

在這里插入圖片描述

那流程的id呢,這是部署以后在數(shù)據(jù)庫(kù)表的id??梢愿鶕?jù)需要自行選擇啟動(dòng)流程的方法。

流程實(shí)例

查詢(xún)所有啟動(dòng)的流程實(shí)例

在這里插入圖片描述

每次開(kāi)始一個(gè)流程以后,就會(huì)生成一個(gè)流程實(shí)例。通過(guò)這個(gè)方法可以查看所有的流程實(shí)例。

測(cè)試流程

package org.example;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.assertj.core.util.DateUtil;
import org.example.common.PrintUtil;
import org.example.entity.User;
import org.example.service.ActivitiService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
@SpringBootTest
public class SpringBootApplicationTest {
    @Resource
    DataSource dataSource;
    @Autowired
    ActivitiService activitiService;
    @Test
    void context() throws SQLException {
        System.out.println(dataSource.getConnection());
    }
    @Test
    public void deployProcess(){
        activitiService.deployProcess();
    }
    @Test
    public void TestStartProcess(){
        ProcessDefinition processDefinition = activitiService.getAllProcessDefinition().get(0);
        String bussinessKey = this.getClass().getSimpleName();
        Map<String , Object> map = new HashMap<String , Object>();
        map.put("creator","Echo");
        activitiService.startProcess(processDefinition.getId(),bussinessKey,map);
    }
    @Test
    public void findAllDeployment(){
        List<Deployment> list = activitiService.getAllDeployment();
        PrintUtil.printTable(list);
    }
    @Test
    public void findAllProcessDefinition(){
        List<ProcessDefinition> list = activitiService.getAllProcessDefinition();
        PrintUtil.printTable(list);
    }
    @Test
    public void findAllProcessInstance(){
        List<ProcessInstance> list = activitiService.getAllProcessInstance();
        PrintUtil.printTable(list);
    }
    @Test
    public void findAllProcessTask(){
        List<Task> list = activitiService.getAllProcessTask();
        PrintUtil.printTable(list);
    }
    @Test
    public void findTaskByUserId(){
        String userId = "keaizp";
        List<Task> list = activitiService.getAllProcessTaskByCandidateOrAssigned(userId);
        PrintUtil.printTable(list);
    }
    @Test
    public void claimTask(){
        String userId="keaizp";
        List<Task> list = activitiService.getAllProcessTaskByCandidate(userId);
        PrintUtil.printTable(list);
        activitiService.claimTask(list.get(0),userId);
        list = activitiService.getAllProcessTaskByCandidate("zengpei");
        PrintUtil.printTable(list);
    }
    @Test
    public void complateUserTask(){
        String userId = "Echo";
        List<Task> list = activitiService.getAllProcessTaskByAssigned(userId);
        List<String> candidateUsers = new ArrayList<String>();
        candidateUsers.add("keaizp");
        candidateUsers.add("zengpei");
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("approver",candidateUsers);
        activitiService.complateTask(list.get(0),map);
    }
    @Test
    public void processDefinitionXml(){
        List<ProcessDefinition> list = activitiService.getAllProcessDefinition();
        String xmlStr = activitiService.getProcessDefinitionXml(list.get(0).getId());
        System.out.println(xmlStr);
    }
    @Test
    public void findHistoryByBusinessKey(){
        List<HistoricProcessInstance> list = activitiService.getHistoryByBusinessKey("2023-07-02T22:45:45");
        PrintUtil.printTable(list);
    }
    @Test
    public void printTest(){
        List<User> users = new ArrayList<>();
        users.add(new User("keaizpeeeeeeeee",24,"male"));
        users.add(new User("Echo",24,"male"));
        users.add(new User("nick",24,"male"));
        users.add(new User("amy",24,"male"));
        PrintUtil.printTableFixed(users,16);
    }
}

啟動(dòng)流程

在這里插入圖片描述

這里我用的是一個(gè)格式化的日期做bussinessKey,實(shí)際業(yè)務(wù)中最好使用 流程作業(yè)類(lèi)型 + 一個(gè)業(yè)務(wù)臺(tái)賬id,比如:請(qǐng)假申請(qǐng)要走審批流程, 離職申請(qǐng)也要走審批流程,如果只用id作為bussinessKey的話(huà),bussinessKey就無(wú)法滿(mǎn)足唯一性。所以最好 前面加上作業(yè)類(lèi)型。這里的map傳入的是流程圖里面的參數(shù)。

在這里插入圖片描述

傳入受理人,這里就會(huì)產(chǎn)生一個(gè)Task,就是用戶(hù)的代辦任務(wù)。

完成任務(wù)

在這里插入圖片描述
當(dāng)用戶(hù)登錄系統(tǒng)的時(shí)候,應(yīng)該給用戶(hù)提示,用戶(hù)有未完成的代辦事項(xiàng),然后給出用戶(hù)代辦事項(xiàng)列表,做完一切以后,就是完成用戶(hù)任務(wù),這個(gè)時(shí)候,可以傳入下一流程節(jié)點(diǎn)參與任務(wù)的人,當(dāng)然你也可以傳入幾個(gè)候選人,candidate Users就是 候選人。可以傳入一個(gè)用戶(hù)id的列表,然后這幾個(gè)人就會(huì)收到可以受理的任務(wù),可以選擇是否接受該任務(wù)。只要接受了任務(wù),其他候選人就無(wú)法再接受此任務(wù),同時(shí)這個(gè)任務(wù)的Assignee就會(huì)設(shè)置成受理人的id

受理任務(wù)

在這里插入圖片描述
因?yàn)橛脩?hù)“keaizp”成為了候選者,他就可以看到自己可以受理的這個(gè)任務(wù),用claim方法就可以受理該任務(wù),當(dāng)受理任務(wù)完成以后,再去看看另外一名候選者的受理任務(wù),會(huì)發(fā)現(xiàn)已經(jīng)沒(méi)有待受理的任務(wù)了。

以上就是Springboot整合Activiti操作詳解的詳細(xì)內(nèi)容,更多關(guān)于Springboot整合Activiti的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論