Camunda大杂烩(一:搭建)

环境

自己瞎折腾,抽空整的Spring Cloud Alibaba 2.2.7 + Camunda 7.17.0大杂烩版本,想啥都加点进去,这边就记录一下Camunda的部分,后续有空再加上其他部分吧(不需要的可以忽略spring cloud alibaba的部分)

配置

父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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.grey.demo</groupId>
    <artifactId>demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <modules>
        <module>demo_user_service</module>
        <module>demo_gateway</module>
        <module>demo_business_service</module>
        <module>demo_commons</module>
    </modules>

    <properties>
        <spring.cloud-version>2021.0.0</spring.cloud-version>
        <spring.boot-version>2.6.2</spring.boot-version>
        <spring.cloud.alibaba-version>2.2.7.RELEASE</spring.cloud.alibaba-version>
        <lombok-version>1.16.20</lombok-version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--springcloud-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


</project>

子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>
        <artifactId>demo</artifactId>
        <groupId>com.grey.demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>camunda</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>camunda</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.camunda.bpm</groupId>
                <artifactId>camunda-bom</artifactId>
                <version>7.17.0</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>


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

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>javax.ws.rs</groupId>
                    <artifactId>jsr311-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.camunda.bpm.springboot</groupId>
            <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
        </dependency>

        <dependency>
            <groupId>org.camunda.bpm.springboot</groupId>
            <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.camunda.bpm</groupId>
            <artifactId>camunda-engine-plugin-spin</artifactId>
        </dependency>

        <dependency>
            <groupId>org.camunda.spin</groupId>
            <artifactId>camunda-spin-dataformat-all</artifactId>
        </dependency>

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

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

    </dependencies>

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

</project>

yml文件

server:
  port: 9077

spring:
  application:
    name: demo-camunda-service
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher # spring boot版本问题
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 #Nacos服务注册中心地址
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://####/camunda
    username: ####
    password: ####

camunda:
  bpm:
    admin-user:
      id: demo
      password: demo
    filter:
      create: All tasks
    database:
      schema-update: true

processes.xml

需要在以下路径新建这样一个文件

<process-application
        xmlns="http://www.camunda.org/schema/1.0/ProcessApplication"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <process-archive name="loan-approval">
        <process-engine>default</process-engine>
        <properties>
            <property name="isDeleteUponUndeploy">false</property>
            <property name="isScanForProcessDefinitions">true</property>
        </properties>
    </process-archive>

</process-application>

 

绘图

绘图这边使用官方工具,camunda-modeler,流程图如下,由于是大杂烩,所以一个流程里包括了

1、普通流程(三级领导审批)

2、串行流程(二级领导审批)

3、并行流程(一级领导审批)

 串行变量

这边尤其强调一下串行变量

Collection:指集合名称(所有需要审批人的标识列表)

Element Variable:集合内的元素变量(当处于某个审批人时,该变量里存的会是当前审批人的标识)

Completion Condition:向下流转的条件(这边没设值,会导致必须串行人员全部审批完才能继续走下去)

 

 

 

 

 

 

基础方法

这边列举几个会经常用到的service

RuntimeService

进行时操作(流程实例):开启流程/删除流程/流程挂起、激活/获取流程内变量等操作

TaskService

任务相关操作:任务完成/任务挂起/任务查询/任务删除/任务内变量等操作

RepositoryService

拓扑图部署/删除、流程相关查询等等(与上面的区别是,上面是流程实例,此处为部署的流程)

 

获取当前部署的全部bpm

由于camunda会记录历史版本,所以你对流程结构进行了修改了一次,就会发现有两个结果

package com.grey.demo.camunda.service.impl;

import com.grey.demo.camunda.controller.response.ProcessDefinitionResponseDTO;
import com.grey.demo.camunda.service.IDeploymentService;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 流程引擎部署相关服务
 *
 * @author 话离小小灰
 * @since 2022/5/11
 */
@Service
public class DeploymentServiceImpl implements IDeploymentService {


    /**
     * camunda定义服务类
     */
    @Resource
    private RepositoryService repositoryService;


    @Override
    public List<ProcessDefinitionResponseDTO> queryProcessDefinitionPages(int firstResult, int maxResults) {
        // 构建返回值
        List<ProcessDefinitionResponseDTO> processDefinitionResponseDTOS = new ArrayList<>();
        // 查询全部已部署的流程
        List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().listPage(firstResult, maxResults);
        processDefinitions.forEach(processDefinition -> {
            ProcessDefinitionResponseDTO processDefinitionResponseDTO = new ProcessDefinitionResponseDTO();
            BeanUtils.copyProperties(processDefinition, processDefinitionResponseDTO);
            processDefinitionResponseDTOS.add(processDefinitionResponseDTO);
        });

        return processDefinitionResponseDTOS;
    }
}

示例结果(同一张bpm,但是存在两个版本):

一些基础操作

对于流程开启、任务查询、任务完成的基础操作

package com.grey.demo.camunda.service.impl;

import com.grey.demo.camunda.service.ICamundaService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 流程引擎实现类
 *
 * @author 话离小小灰
 * @since 2022/5/7
 */
@Service
public class CamundaServiceImpl implements ICamundaService {

    /**
     * 运行实例的业务类
     */
    @Resource
    private RuntimeService runtimeService;

    /**
     * 任务相关的业务类
     */
    @Resource
    private TaskService taskService;

    /**
     * 开启流程
     *
     * @param processDefinitionKey 流程定义key
     * @return 流程
     */
    public ProcessInstance startProcess(String processDefinitionKey) {
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
        if (instance == null) {
            throw new RuntimeException("开启流程失败");
        }
        return instance;
    }
    
    /**
     * 开启流程
     *
     * @param processDefinitionKey 流程定义key
     * @param map                  参数
     * @return 流程
     */
    public ProcessInstance startProcess(String processDefinitionKey, Map<String, Object> map) {
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, map);
        if (instance == null) {
            throw new RuntimeException("开启流程失败");
        }
        return instance;
    }
    
    /**
     * 根据组获取task
     *
     * @param group 组
     * @return 任务列表
     */
    public List<Task> getTasksListByGroup(String group) {
        return taskService.createTaskQuery().taskCandidateGroup(group).list();
    }
    
    /**
     * 根据组获取tasks
     *
     * @param groups 组
     * @return 任务列表
     */
    public List<Task> getTaskCandidateGroupIn(List<String> groups) {
        return taskService.createTaskQuery().taskCandidateGroupIn(groups).list();
    }
    
    /**
     * 根据用户获取任务列表
     *
     * @param userId 用户ID
     * @return 任务列表
     */
    public List<Task> getTasksListByUser(String userId) {
        return taskService.createTaskQuery().taskCandidateUser(userId).list();
    }
    
    /**
     * 根据用户名获取任务列表
     *
     * @param userName 用户名称
     * @return 任务列表
     */
    public List<Task> getTaskListByTaskAssignee(String userName) {
        return taskService.createTaskQuery().taskAssignee(userName).list();
    }
    
    /**
     * 根据任务名称获取任务列表
     *
     * @param taskName 任务名称
     * @return 任务列表
     */
    public List<Task> getTaskListByTaskName(String taskName) {
        return taskService.createTaskQuery().taskName(taskName).list();
    }
    
    /**
     * 根据流程号获取任务列表
     *
     * @param flowId 流程号
     * @return 任务列表
     */
    public List<Task> getTaskListByFlowId(String flowId) {
        return taskService.createTaskQuery().processInstanceId(flowId).list();
    }
    
    /**
     * 根据任务名称和组获取任务列表
     *
     * @param taskName 任务名称
     * @param group    组
     * @return 任务列表
     */
    public List<Task> getTaskListByTaskNameAndGroup(String taskName, String group) {
        return taskService.createTaskQuery().taskName(taskName).taskCandidateGroup(group).list();
    }
    
    /**
     * 根据任务ID
     *
     * @param taskId 任务ID
     * @return 任务列表
     */
    public List<Task> getTaskListByTaskId(String taskId) {
        return taskService.createTaskQuery().taskId(taskId).list();
    }
    
    /**
     * 任务完成
     * @param taskId 任务ID
     * @return 是否成功
     */
    public boolean taskComplete(String taskId) {
        taskService.complete(taskId);
        return true;
    }
    
    /**
     * 任务完成(带参数)
     * @param taskId 任务ID
     * @param map 参数
     * @return 是否成功
     */
    public boolean taskComplete(String taskId, Map<String, Object> map) {
        taskService.complete(taskId, map);
        return true;
    }
}

 Controller

package com.grey.demo.camunda.controller;

import com.grey.demo.camunda.controller.response.ProcessDefinitionResponseDTO;
import com.grey.demo.camunda.service.ICamundaService;
import com.grey.demo.camunda.service.IDeploymentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.camunda.bpm.engine.task.Task;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * Camunda测试controller
 *
 * @author 话离小小灰
 * @since 2022/5/11
 */
@RestController
@RequestMapping("/camunda")
@Api(tags = "Camunda测试API")
public class CamundaDemoController {

    /**
     * 部署的流程服务类
     */
    @Resource
    IDeploymentService deploymentService;

    /**
     * 流程服务类
     */
    @Resource
    ICamundaService camundaService;

    /**
     * 获取当前部署的全部流程(包括历史版本)TODO 先懒得分页了
     *
     * @param firstResult 开始的游标
     * @param maxResults  结束的游标
     * @return 分页后的数据
     */
    @GetMapping(value = "/listPage")
    @ApiOperation("获取当前部署的全部流程")
    public List<ProcessDefinitionResponseDTO> listPage(int firstResult, int maxResults) {
        return deploymentService.queryProcessDefinitionPages(firstResult, maxResults);
    }

    /**
     * 开始一个流程
     *
     * @param processDefinitionKey 流程key
     * @return 流程内容
     */
    @PostMapping(value = "/start")
    @ApiOperation("开始一个流程")
    public String start(String processDefinitionKey) {
        return camundaService.startProcess(processDefinitionKey).getId();
    }

    /**
     * 下一步操作
     *
     * @param taskId 任务ID
     * @param map    参数
     * @return 是否成功
     */
    @PostMapping(value = "/next")
    @ApiOperation("下一步")
    public Boolean next(String taskId, Map<String, Object> map) {
        return camundaService.taskComplete(taskId, map);
    }

    /**
     * 根据流程号获取任务列表 TODO 直接返回会报错,Task可能需要转换
     *
     * @param flowId 流程ID
     * @return 任务列表
     */
    @GetMapping(value = "/getTasks")
    @ApiOperation("获取任务列表")
    public List<Task> getTasks(String flowId) {
        return camundaService.getTaskListByFlowId(flowId);
    }
}

 

posted @ 2022-05-12 11:20  糖醋小灰  阅读(1423)  评论(0编辑  收藏  举报