(八)、SpringBoot2.x 整合 Activiti7 功能实践

(八)、SpringBoot2.x 整合 Activiti7 功能实践

 

 

 

1、简介

前面的文章我们简单了解了Activiti 的功能(1、简介2、核心表结构和Api3、idea-BPMN插件插件24、SpringBoot2的简单整合5、流程定义的操作6、用户任务7、流程变量8、用户组任务),下面我们进行全面实践。

 

2、创建SpringBoot2.x项目

2.1、maven依赖如下:

<?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.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.dw.study</groupId>
    <artifactId>springboot-activiti7</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-activiti7</name>
    <description>springboot-activiti7</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
       <!-- mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!-- activity 7 -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
        </dependency>

        <!-- pageHelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.1</version>
        </dependency>
          <!-- druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.21</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>

 

2.2、yml配置

server:
  port: 8082

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true
spring:
  application:
    name: spring-boot-activiti
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://localhost:3306/activiti_study?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=utf8
        &autoReconnect=true&failOverReadOnly=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: 123456
      initial-size: 1
      min-idle: 2
      max-active: 20
      max-wait: 60000
      pool-prepared-statements: true
      max-open-prepared-statements: 20
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      max-evictable-idle-time-millis: 900000
      validation-query: SELECT 1
      test-on-borrow: true
      test-on-return: false
      test-while-idle: true
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 2000

#  activity
  activiti:
    #1.false,默认值,acticiti启动时对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常
    #2.true,acticiti会对数据中所有的表进行更新操作,如果表不存在,则自动创建
    #3.create_drop,在acticiti启动时创建表,关闭时删除表(必须手动关闭引擎才能删除表)
    #4.drop_create,在acticiti启动时删除原来的表,然后创建新表(不需要手动关闭引擎)
      database-schema-update: true
    #默认true,效验流程文件,默认效验resources下的processes文件夹里的流程,为true自动部署流程,为false则不部署
      check-process-definitions: true
    # 流程文件存放目录
      process-definition-location-prefix: classpath:/processes/
      async-executor-activate: false
      # 启用历史记录
      db-history-used: true
    #历史记录等级
    #1.none:不保存任何历史记录,因此在流程执行过程中,这是最高效的
    #2.acticiti:级别高于none,保存流程实例与流程行为,其他数据不保存
    #3.audit:除activiti级别会保存的数据外,还会保存全部的流程任务及其属性,audit为默认值
    #4.full:保存历史数据的最高级别,除了保存audit级别的数据外,还会保存其他流程相关的细节数据,包括一些流程参数等
      history-level: full
  profiles:
    active: dev
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration

 

3、创建一个请假的BPMN20流程文件(画图插件

 

3.2、 分配流程节点的处理人

 

 holidayProcess.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" targetNamespace="http://www.activiti.org/processdef" exporter="Camunda Modeler" exporterVersion="4.11.1">
  <process id="holidayProcess" name="holidayProcess" isExecutable="true">
    <startEvent id="sid-6b3151c0-c07a-4106-b56e-31549176b84b" />
    <userTask id="sid-0a26713e-7254-4b26-9af8-e72350b8d008" name="填写请假申请" activiti:assignee="zhangsan" />
    <sequenceFlow id="sid-4c8c2ba6-74ab-46b6-b20d-e55e25ff06c8" sourceRef="sid-6b3151c0-c07a-4106-b56e-31549176b84b" targetRef="sid-0a26713e-7254-4b26-9af8-e72350b8d008" />
    <sequenceFlow id="sid-96180d0e-27e7-4222-ba69-cc9cc0276037" sourceRef="sid-0a26713e-7254-4b26-9af8-e72350b8d008" targetRef="sid-f3ef852e-26b8-4922-9ee9-f514cfcecd15" />
    <userTask id="sid-f3ef852e-26b8-4922-9ee9-f514cfcecd15" name="组长审批" activiti:assignee="lisi" />
    <userTask id="sid-ab723b22-4b15-4868-95da-9449844f304a" name="人事归档" activiti:assignee="wangwu" />
    <sequenceFlow id="sid-13a2993b-e107-4937-8fbb-7a55d7a8af3b" sourceRef="sid-f3ef852e-26b8-4922-9ee9-f514cfcecd15" targetRef="sid-ab723b22-4b15-4868-95da-9449844f304a" />
    <endEvent id="sid-4961da55-0df3-4329-9a41-3058d33bd836" />
    <sequenceFlow id="sid-02e52b8f-3e72-4656-8b8a-93b98a828e9e" sourceRef="sid-ab723b22-4b15-4868-95da-9449844f304a" targetRef="sid-4961da55-0df3-4329-9a41-3058d33bd836" />
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_holidayProcess">
    <bpmndi:BPMNPlane id="BPMNPlane_holidayProcess" bpmnElement="holidayProcess">
      <bpmndi:BPMNEdge id="edge-889da73a-4520-4440-832d-1a50c3c21623" bpmnElement="sid-02e52b8f-3e72-4656-8b8a-93b98a828e9e">
        <omgdi:waypoint x="725" y="119.99998" />
        <omgdi:waypoint x="845" y="119.99998" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-5c5793cc-fc43-471b-ad7f-b8727a840dc6" bpmnElement="sid-13a2993b-e107-4937-8fbb-7a55d7a8af3b">
        <omgdi:waypoint x="530" y="120" />
        <omgdi:waypoint x="625" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-3c84b116-610b-42f6-9112-feebe5c6f203" bpmnElement="sid-96180d0e-27e7-4222-ba69-cc9cc0276037">
        <omgdi:waypoint x="335" y="120" />
        <omgdi:waypoint x="430" y="120" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="edge-02d04728-12aa-42e9-85c1-88c1826a91af" bpmnElement="sid-4c8c2ba6-74ab-46b6-b20d-e55e25ff06c8">
        <omgdi:waypoint x="189.99994000000004" y="120" />
        <omgdi:waypoint x="234.99994" y="119.99998" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="shape-faf46466-ed0e-4a0f-9275-2be818b4207d" bpmnElement="sid-6b3151c0-c07a-4106-b56e-31549176b84b">
        <omgdc:Bounds x="160" y="105" width="30" height="30" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-1ba5dd41-2304-4ae9-b90b-b98ef1d6abb8" bpmnElement="sid-0a26713e-7254-4b26-9af8-e72350b8d008">
        <omgdc:Bounds x="235" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-2e87bf2b-408f-45cb-a393-5fff51be92dc" bpmnElement="sid-ab723b22-4b15-4868-95da-9449844f304a">
        <omgdc:Bounds x="625" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-ceba04e3-3913-4f80-8a9b-40f41acdf148" bpmnElement="sid-4961da55-0df3-4329-9a41-3058d33bd836">
        <omgdc:Bounds x="845" y="105" width="30" height="30" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="shape-3220528e-c4d8-4d42-b057-f89a815d064b" bpmnElement="sid-f3ef852e-26b8-4922-9ee9-f514cfcecd15">
        <omgdc:Bounds x="430" y="80" width="100" height="80" />
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
View Code

 

4、启动应用程序

4.1 启动之后数据库会自动创建25张表

4.2、启动项目会自动部署processes包下面的holidayProcess.bpmn20.xml文件,流程部署修改的表:

1、act_re_deployment 流程部署(部署名称、部署时间)

 

 2、act_ge_bytearray (存储流程部署的id、bmpn-xml文件、资源名称)

 

 3、act_re_procdef 流程定义表(存储:类别、流程名称、流程key、部署的id、资源名称)

  id 属性设置为 {processDefinitionKey}:{processDefinitionVersion}:{generated-id},其中generated-id是添加的唯一编号,以保证集群环境中进程定义缓存的进程 ID 的唯一性。

4.3、如果流程文件有修改, 重新启动项目会再次部署。

 

3、启动流程实例

(一)启动流程实例:  流程实例的key 为xml 中定义的Key:

   /**
     * 2、启动流程实例
     */
    @Test
    public void runProcess() {
        // 1、创建ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayProcess");
        log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());
    }

 

(二)启动流程修改的表

1、act_ru_execution(运行时流程执行实例数据表,一条是开始事件的执行实例,这个一直存在,只到流程结束后才会自动删除,is_active字段表示是否正在执行实例),开始-->填写请假申请。所以有两条记录。

 

 2、act_ru_task(运行时任务信息数据信息表)

 

3、act_ru_identitylink

 

 4、act_hi_taskinst(历史任务实例数据表)

 

 5、act_hi_procinst(历史流程实例数据表,正在执行的任务也在其中)

 

 6、 act_hi_actinst(历史节点数据,图片上的节点信息)

 

 7、act_hi_identitylink(历史流程参与用户信息数据表)

 

 

4、查询个人代办任务

(一)代码实现

  /**
     * 查询个人代办任务
     */
    @Test
    public void queryPersonJob() {
        //1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2、获取taskService
        TaskService taskService = processEngine.getTaskService();
        //3、根据流程key 和 任务的负责人 查询任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess") //流程Key
                .taskAssignee("zhangsan")  //要查询的负责人
                .list();
        //4、输出
        for (Task task : taskList) {
            System.out.println("流程实例id= " + task.getProcessInstanceId());
            System.out.println("任务Id= " + task.getId());
            System.out.println("任务负责人= " + task.getAssignee());
            System.out.println("任务名称= " + task.getName());
        }
    }

(二)查询过程

查询以下sql语句(ACT_RU_TASK 与 ACT_RE_PROCDEF关联查询)

select 
   distinct RES.* 
from ACT_RU_TASK RES 
inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ 
WHERE RES.ASSIGNEE_ = 'zhangsan' and D.KEY_ = 'holidayProcess' 
order by RES.ID_ asc
LIMIT 2147483647 OFFSET 0 

 

5、完成个人任务

 (一)代码实现(依次完成张三、李四、王五的任务)

/**
     * 完成 zhangsan 的任务
     */
    @Test
    public void finishPersonJob(){
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取操作任务的服务 TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess") //流程Key
                .taskAssignee("zhangsan")  //要查询的负责人
                .singleResult();
        // 完成任务,参数:任务id
        taskService.complete(task.getId());
    }

    /**
     * 完成 lisi 的任务
     */
    @Test
    public void finishPersonJob2(){
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取操作任务的服务 TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess") //流程Key
                .taskAssignee("lisi")  //要查询的负责人
                .singleResult();
        // 完成任务,参数:任务id
        taskService.complete(task.getId());
    }

    /**
     * 完成 wangwu 的任务
     */
    @Test
    public void finishPersonJob3(){
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取操作任务的服务 TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess") //流程Key
                .taskAssignee("wangwu")  //要查询的负责人
                .singleResult();
        // 完成任务,参数:任务id
        taskService.complete(task.getId());
    }

 

( 二 )、完成个人任务修改的表

1、ACT_HI_TASKINST(历史的任务实例表)

操作:1、修改上一个节点的结束时间;   2、插入下一个待执行的任务以及开始时间。

    1.1、zhangsan完成任务(插入下一个lisi的任务实例组长审批修改 zhangsan 任务实例 end_time加入处理完结时间)

   1.2、lisi 完成任务(插入下一个wangwu的任务实例,lisi 的任务实例 end_time 加入处理完结时间)

 

   1.3、wangwu完成任务(修改人事归档的结束时间)

 

 2、ACT_HI_ACTINST(历史节点数据) 2.1、修改上一个节点的结束时间,2.2、插入下一个待执行的节点,以及节点的开始时间。

    2.1、zhangsan完成任务(插入下一个组长审批节点,节点中taskid为运行时任务信息表中的id,  修改请假申请节点end_time 字段 加入处理完结时间)

   2.2、lisi 完成任务(插入下一个人事归档节点,节点中 taskid为运行时任务信息表中的id,  组长审批节点的 end_time 字段加入处理完结时间)

 

 

   2.3、wangwu完成任务(修改人事归档的结束时间, 插入endEvent)

 

 3、ACT_HI_IDENTITYLINK(历史流程参与用户信息数据表)

   3.1、zhangsan完成任务(插入lisi负责人)

    3.2、lisi 完成任务(插入wangwu负责人)

 

 

 4、ACT_RU_TASK(运行时任务信息数据信息表)操作:1、删除了上一个任务, 2、插入了下一个节点的任务。

   4.1、zhangsan完成任务(删除了zhangsan的请假申请的任务,添加了组长审批任务记录)

   4.2、lisi 完成任务(删除lisi组长审批的任务,添加了人事归档的任务记录)

 

    4.3、wangwu完成任务, 删除正在运行的任务数据。

 

 5、ACT_RU_IDENTITYLINK(运行时用户信息数据)当流程执行完时会删除该流程的所有参与人,在历史记录表中可以查看所有的参与者。

    5.1、zhangsan完成任务(插入lisi负责人)

     5.2、lisi完成任务(插入wangwu负责人)

    5.3、wangwu完成任务(删除正在运行的实例的参与者)

 

 6、ACT_RU_EXECUTION(运行时流程执行实例数据表)修改ACT_id为下一个执行的节点id, 任务执行完毕会删除记录。

   6.1、zhangsan完成任务(第二条记录ACT_ID_改为下一个的节点的id(组长审批))

 

    6.2、lisi 完成任务(第二条记录ACT_ID_改为下一个的节点的id(人事归档))

    6.3、wangwu完成任务删除流程执行实例

 

6、查看历史信息

(一)代码实现

 /**
     * 查询流程执行历史
     */
    @Test
    public void queryHistory() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
        // 获取历史流程实例
        HistoricProcessInstanceQuery holidayProcess = historyService.createHistoricProcessInstanceQuery()
                .processDefinitionKey("holidayProcess");
        HistoricProcessInstance historicProcessInstance = holidayProcess.singleResult();
        String superProcessInstanceId = historicProcessInstance.getSuperProcessInstanceId();
        // 创建历史运行查询
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(superProcessInstanceId);

        // 增加排序操作,根据开始时间排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        //查询所有内容
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
        //  输出
        for (HistoricActivityInstance hi : activityInstanceList) {
            System.out.println("节点id:" + hi.getActivityId());
            System.out.println("节点名字:" + hi.getActivityName());
            System.out.println("流程定义key: " + hi.getProcessDefinitionId());
            System.out.println("流程实例id: " + hi.getProcessInstanceId());
            System.out.println("<==========================>");
        }
    }

 

输出:

节点id:sid-6b3151c0-c07a-4106-b56e-31549176b84b
节点名字:null
流程定义key: holidayProcess:1:db04ed98-bd71-11ec-8e0d-00ff0f6cf7db
流程实例id: f67a5872-bd71-11ec-9f77-00ff0f6cf7db
<==========================>
节点id:sid-0a26713e-7254-4b26-9af8-e72350b8d008
节点名字:填写请假申请
流程定义key: holidayProcess:1:db04ed98-bd71-11ec-8e0d-00ff0f6cf7db
流程实例id: f67a5872-bd71-11ec-9f77-00ff0f6cf7db
<==========================>
节点id:sid-f3ef852e-26b8-4922-9ee9-f514cfcecd15
节点名字:组长审批
流程定义key: holidayProcess:1:db04ed98-bd71-11ec-8e0d-00ff0f6cf7db
流程实例id: f67a5872-bd71-11ec-9f77-00ff0f6cf7db
<==========================>
节点id:sid-ab723b22-4b15-4868-95da-9449844f304a
节点名字:人事归档
流程定义key: holidayProcess:1:db04ed98-bd71-11ec-8e0d-00ff0f6cf7db
流程实例id: f67a5872-bd71-11ec-9f77-00ff0f6cf7db
<==========================>
节点id:sid-4961da55-0df3-4329-9a41-3058d33bd836
节点名字:null
流程定义key: holidayProcess:1:db04ed98-bd71-11ec-8e0d-00ff0f6cf7db
流程实例id: f67a5872-bd71-11ec-9f77-00ff0f6cf7db
<==========================>

 

7、与业务表关联

(一)代码实现(使用关联id启动流程)

  @Test
    public void runProcessByBusinessKey() {
         // 1、获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3、启动流程的过程中,添加businesskey
        // 第二个参数:businessKey,业务表的id,就是 10010
        ProcessInstance instance = runtimeService.
                startProcessInstanceByKey("holidayProcess", "10010");
        // 4、输出
        System.out.println("businessKey=="+instance.getBusinessKey());
    }

 (二)与普通方式启动实例比较

1. ACT_HI_PROCINST(历史流程实例数据表比较,普通启动business_key为空,说明业务表的id存在这个字段中)

 

2. ACT_RU_EXECUTION(运行时流程执行实例数据表比较,普通启动business_key为空,说明业务表的id存在这个字段中)

 

八、使用变量分配执行人

(一)、设置流程变量

(二)、流程启动时设置流程变量(也可以运行时设置)代码实现:

  @Test
    public void runProcessAndSetVariables() {
        // 获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 设定assignee的值,用来替换uel表达式
        Map<String, Object> assigneeMap = new HashMap<>();
        assigneeMap.put("assignee1", "zhangsan");
        assigneeMap.put("assignee2", "lisi");
        assigneeMap.put("assignee3", "wangwu");
        //  启动流程实例
        runtimeService.startProcessInstanceByKey("holidayProcess", assigneeMap);
    }

 额外修改的表

 

九、候选人实例介绍

(一)设置候选人

 (二)、启动流程。。。

 (三)、 查询候选人任务

  /**
     * 查询候选人任务
     */
    @Test
    public void queryCandidateUserJob() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取TaskService
        TaskService taskService = processEngine.getTaskService();
        // 查询组任务
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess")
                .taskCandidateUser("zhangsan") //根据候选人查询任务
                .list();
        for (Task task : taskList) {
            System.out.println("========================");
            System.out.println("流程实例ID=" + task.getProcessInstanceId());
            System.out.println("任务id=" + task.getId());
            System.out.println("任务负责人=" + task.getAssignee());
        }
    }

 提示错误:

org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.springframework.security.core.userdetails.UsernameNotFoundException: zhangsan
### Cause: org.springframework.security.core.userdetails.UsernameNotFoundException: zhangsan

解决方案:

1、实现UserDetailsService接口

@Component
public class CustomUserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userService.findOneUserByName(username);
    }
}

 

2、userService

@Service
public class UserService {
    private final Logger logger = LoggerFactory.getLogger(UserService.class);

    public MyUser findOneUserByName(String username) {
        logger.info("username:"+  username);
        // 查询数据库获取权限(我这里伪造)
        List<GrantedAuthority> authorities= AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
        MyUser myUser = new MyUser();
        myUser.setUserName(username);
        myUser.setAuthorities(authorities);
        return myUser;
    }
}

4、MyUser

@Data
public class MyUser implements UserDetails {

    private String userName;

    private List<GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getUsername() {
        return userName;
    }

    @Override
    public String getPassword() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }
}

 

查询结果:

========================
流程实例ID=3fd660ed-bd9a-11ec-aa6b-00ff0f6cf7db
任务id=3fda5897-bd9a-11ec-aa6b-00ff0f6cf7db
任务负责人=null
========================
流程实例ID=a667bb6c-bd97-11ec-a8d7-00ff0f6cf7db
任务id=a66bb314-bd97-11ec-a8d7-00ff0f6cf7db
任务负责人=null

 

(四)、wanger拾取任务代码实现:

    /**
     * 拾取任务
     */
    @Test
    public void claimJob() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取TaskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess")
                .taskCandidateUser("wanger").singleResult();//根据候选人查询任务
          // 任务候选人
        String candidateUser = "wanger";
        // 查询任务
        if (task != null) {
            // 拾取任务
            taskService.claim(task.getId(), candidateUser);
            System.out.println("taskid-" + task.getId() + "-用户-" + candidateUser + "-拾取任务完成");
        }
    }

 拾取任务前后对比

 

 

 (五)wanger归还任务、交接任务代码实现:

总的来说就是改assignee_字段:  归还任务设置成null;  交接任务设置成lisi

  @Test
    public void changeAssignUser() {
        //获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取TaskService
        TaskService taskService = processEngine.getTaskService();
        //根据key 和负责人来查询任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayProcess")
                .taskCandidateUser("wanger").singleResult();//根据候选人查询任务
        if (task != null) {
            //归还任务 ,就是把负责人 设置为空
            taskService.setAssignee(task.getId(), null);
            taskService.setAssignee(task.getId(), "lisi");
            System.out.println("taskid-" + task.getId() + "-归还任务完成");
        }
    }

 

 十、监听器

 

 (二)、代码实现

@Slf4j
public class MyTaskListener implements TaskListener {
    //delegateTasK是当前任务的对象
    @Override
    public void notify(DelegateTask delegateTask) {
        log.info("执行 MyTaskListener....");
        //默认是create事件
        if("填写请假申请".equals(delegateTask.getName()) &&
                "create".equals(delegateTask.getEventName())){
            delegateTask.setAssignee("张三");
        }
    }
}

控制台日志:

 

 数据库:

 

posted @ 2022-04-10 15:01  邓维-java  阅读(2010)  评论(0编辑  收藏  举报