跟铁拐李李老师学习工作流的第二天


Day02:流程中心 - 管理员操作

今日学习目标:

  1. 掌握前端vue工程的编译、启动和部署
  2. 掌握模型、流程图、模型定义的含义和相互关系
  3. 掌握模型的基本操作:增、删、改、查
  4. 掌握流程图的操作:保存、部署、展示
  5. 掌握流程定义的操作:查询、删除、下载资源等
  6. 掌握流程定义的激活、挂起操作

需求分析

  1. 在流程审批系统中,管理员需要做的事情包括以下两类:
  • 设计流程图
  • 保存流程图、部署(发布)流程图

在这里插入图片描述
设计流程图有两种方式:

  • 一种是使用第一天讲解的方式,用actiBPMN设计一个流程图,把流程图上传到服务器上,然后进行保存、发布、使用。
  • 第二种方式是直接在系统中设计流程图,这种方式避免了上传流程图的过程,是主流的开发方式。

本项目采用的就是第二种方式,即在线流程设计。这个方式需要一个在线流程设计器,这是一种前端解决方案,有很多前端组件可以供我们选择使用。
在这里插入图片描述注意:上图中大部分操作只需要在前端进行。

  1. 我们需要开发的是如何将前端框架生成的文件进行保存、部署、查询等操作。本质上是一些对象的增删改查。
  • 模型管理
    在这里插入图片描述
    流程定义管理
    在这里插入图片描述

2. 在线设计器

2.1. bpmn2.0规范

为什么一个mysql的数据库脚本,可以在不同公司的mysql数据库上执行?

答案是规范,也就是说这些mysql数据库,都遵循了相同的规范和标准,所以数据库实例是可以共用的。相同的例子还有:

  • 一个word文档,可以在不同的机器上打开,只要这些机器都安装了office程序
  • 一个pdf文件,可以在不同机器上打开,但是需要安装pdf阅读器
  • 一个java程序,可以在不同人的idea里打开

在这里插入图片描述
activiti的流程图,满足了bpmn2.0规范
在这里插入图片描述

我们将第一天设计的bpmn文件,保存成以下是一个符合bpmn2.0规范的xml文件,这个文件可以被其他bpmn设计器打开、解析。


![在这里插入图片描述](https://img-blog.csdnimg.cn/9be8287cb6284ddd9c53c2048ad04c45.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2k56Ss,size_20,color_FFFFFF,t_70,g_se,x_16)

2.2. bpmn-js框架

在线流程设计器是一个前端的框架,可以方便的集成到我们的项目的前端工程中。
bpmn-js是一个BPMN2.0的工具包和web建模器
JavaScript编写,轻松嵌入到任何web应用。
既可以是web查看器也可以是web建模器。
官网:https://bpmn.io/toolkit/bpmn-js/
源码:https://github.com/bpmn-io/bpmn-js
案例:https://bpmn.io/toolkit/bpmn-js/examples/
演示:https://demo.bpmn.io/
在这里插入图片描述

2.3. 前端工程

2.3.1 工程介绍

流程中心的前端工程使用的是vue框架,集成了bpmn-js框架。

目录结构:

在这里插入图片描述
服务端口:

在这里插入图片描述前端工程有两种启动方式,本地源代码启动和服务器端部署启动。本地源码启动需要在本机安装nodejs,并执行编译命令。服务器端启动则可以直接将编译后的程序部署到nginx服务器中。

为简便起见,推荐使用服务器端启动。

2.3.2 本地启动

  • 编译
npm install

启动

npm run serve

访问
在这里插入图片描述

2.3.3 服务器启动

通过以下方式部署生产环境

  • 生成
npm run build

前端工程中的dist目录中的文件拷贝到Nginx的工程目录、改名
在这里插入图片描述
修改nginx.conf文件
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

	location /api {
        proxy_pass   http://127.0.0.1:8090/;
    }

启动Nginx、页面访问

在这里插入图片描述

3. 模型管理

3.1 工程改造

前端工程师开发的前端项目,需要后端工程提供服务,我们在第一天项目基础上进行改造。改造完成后,进行前文需求分析章节里提到的功能接口的开发。

3.1.1. 更新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>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.itheima</groupId>
    <artifactId>itcast-workflow</artifactId>
    <version>0.0.1</version>
    <name>${project.artifactId}</name>
    <description>itcast-workflow</description>
    <packaging>jar</packaging>

    <properties>
        <java.version>1.8</java.version>
        <activiti.version>7.1.0.M6</activiti.version>
        <knife4j.version>3.0.2</knife4j.version>
        <spring-cloud.version>2020.0.3</spring-cloud.version>
        <spring-plugin.version>2.0.0.RELEASE</spring-plugin.version>
        <jwt.version>0.9.1</jwt.version>
        <druid.version>1.2.6</druid.version>
        <mybatis-plus.version>3.4.2</mybatis-plus.version>
        <mybatis.version>3.5.6</mybatis.version>
        <fastjson.version>1.2.62</fastjson.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <!-- Activiti -->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-image-generator</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!--    mysql   -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--   mybatis   -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!--    druid   -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.0.7</version>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>${knife4j.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.plugin</groupId>
                    <artifactId>spring-plugin-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.plugin</groupId>
                    <artifactId>spring-plugin-metadata</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-core</artifactId>
            <version>${spring-plugin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.plugin</groupId>
            <artifactId>spring-plugin-metadata</artifactId>
            <version>${spring-plugin.version}</version>
        </dependency>

        <!-- md5 工具类 -->
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

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

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jwt.version}</version>
        </dependency>

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>itheima</id>
            <name>itheima</name>
            <url>http://repo.itheima.net/repository/maven-public/</url>
        </repository>
    </repositories>

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

3.1.2. 更新yml文件

server:
  port: 8090

spring:
  application:
    name: 流程审批中心
  datasource: # JDBC配置
    druid:
      url: jdbc:mysql://localhost:3306/itcast_workflow?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
      username: root
      password: root
      # 连接池配置(通常来说只需要修改initial-size,min-idle,mac-active)
      initial-size: 1
      max-active: 20
      min-idle: 1
      #  获取连接等待的超时时间
      max-wait: 60000
      #打开PSCache,并且指定每个连接上PSCache的大小
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      validation-query: SELECT 'x'
      test-on-borrow: false
      test-on-retur: false
      test-while-idle: true
      # 配置间隔多久进行一次检查,检查需要关闭的空闲连接,单位毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在连接池中最小的生存时间,单位毫秒
      min-evictable-idle-time-millis: 300000
      # 配置多个英文逗号分割
      filters: stat
  activiti:
    db-history-used: true  #使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表,历史表没有建立
    history-level: full    #记录全部历史操作
    database-schema-update: true   #自动建表
    #    flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。
    #    true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。
    #    create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。
    #    drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎
    check-process-definitions: false # 自动部署验证设置:true-开启(默认)、false-关闭  在resource目录下添加processes文件夹,并且文件夹不能为空
    #    main:
    #      allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
    database-schema: atc  #置建表策略,如果没有表,自动创建表  修改这个地方为大写
    #关闭springAutoDeployment自动部署流程定义
    deployment-mode: never-fail
  main:
    allow-bean-definition-overriding: true
swagger:
  enabled: true

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    auto-mapping-behavior: full
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: ID_WORKER

3.1.3. 清空数据库

删除数据库中所有的表

3.1.4. 导入公共类

common包和config包是一些基础公共的类,导入到项目里。
在这里插入图片描述

  1. Result类:这个类是用于封装给前端的返回一个统一的对象,这个对象便于前端统一解析和处理
  2. SpringContextHolder:spring上下文的工具类,包含获取bean、设置bean、判断bean等方法
  3. WorkflowException:统一封装运行时异常
  4. ConfigurationSupport:webmvc的配置类,实现Swagger的配置类和一些方法的实现
  5. ExceptionConfiguration:
  6. MybatisPlusConfig:mybatisplus的分页插件

3.2. 模型管理

3.2.1 需求分析

在这里插入图片描述
模型管理是针对模型对象的一些操作,这些将是我们开发的接口:

  • 保存模型对象的基本信息
  • 保存模型对象的流程图
  • 查询模型对象的列表
  • 删除模型对象
  • 部署模型对象
  • 查询部署后生成的流程定义
  • 挂起模型对象
  • 启用挂起的模型对象

因为我们使用的是Activiti框架,此框架提供了一系列实体对象,如模型类:org.activiti.engine.repository.Model。

在本项目中对于一个Activiti对象的增删改查操作,开发过程是:
在这里插入图片描述
DTO:模型传输对象**(如:ModelDTO),dto的字段是根据产品原型得到的。

  • 前端到后端的数据传输对象
  • 分页查询返回的结果

导入DTO对象:
在这里插入图片描述

3.2.2. 新增

在这里插入图片描述
ModelerController

package com.itheima.activiti.controller.modeler;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.activiti.common.Result;
import com.itheima.activiti.dto.modeler.ModelDTO;
import com.itheima.activiti.service.modeler.ModelerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/modeler")
@Api(tags = "模型管理")
public class ModelerController {
    @Autowired
    ModelerService modelerService;

    /**
     * 保存流程模型
     * @param modelDTO
     * @return
     */
    @PostMapping
    @ApiOperation(value = "新增模型")
    public Result save(@RequestBody ModelDTO modelDTO){
        //调用服务的方法
        modelerService.save(modelDTO);

        return Result.success();
    }
}

ModelerService:

package com.itheima.activiti.service.modeler;

import com.itheima.activiti.dto.modeler.ModelDTO;

public interface ModelerService {
    /**
     * 保存模型
     */
    String save(ModelDTO modelDTO);
}

ModelerServiceImpl

package com.itheima.activiti.service.modeler.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.itheima.activiti.dto.modeler.ModelDTO;
import com.itheima.activiti.service.modeler.ModelerService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ModelerServiceImpl implements ModelerService {
    @Autowired
    RepositoryService repositoryService;

    @Autowired
    ObjectMapper objectMapper;

    @Override
    public String save(ModelDTO modelDTO) {
        //创建activiti模型对象
        Model model = repositoryService.newModel();

        //设置模型的基本属性
        model.setKey(modelDTO.getKey());
        model.setName(modelDTO.getName());

        //设置模型的mateInfo
        ObjectNode objectNode = objectMapper.createObjectNode();
        objectNode.put("name", modelDTO.getName());
        objectNode.put("description", modelDTO.getDescription());
        objectNode.put("reversion", model.getVersion());
        model.setMetaInfo(objectNode.toString());

        //保存模型
        repositoryService.saveModel(model);

        return model.getId();
    }
}
### 3.2.3. 列表
![在这里插入图片描述](https://img-blog.csdnimg.cn/e5399a489b30487687be217fad0ff91a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2k56Ss,size_20,color_FFFFFF,t_70,g_se,x_16)
**ModelerController**:

```java
	/**
     * 分页查询、搜索
     *
     */
    @GetMapping("/page")
    @ApiOperation(value = "分页模型")
    public Result<Page<ModelDTO>> page(ModelDTO modelDTO,
                               @RequestParam(required = false, defaultValue = "1") int page,
                               @RequestParam(required = false, defaultValue = "10") int pageSize){
        log.info("page = {}, pageSize = {}", page, pageSize);

        Page<ModelDTO> list = modelerService.page(modelDTO, page, pageSize);
        return Result.success(list);
    }

ModelService:

	/**
     * 分页查询页面设计的模型
     * @param modelDTO
     * @param page
     * @param pageSize
     * @return
     */
    Page<ModelDTO> page(ModelDTO modelDTO, int page, int pageSize);

ModelerServiceImpl

页面上的信息包含:模型的属性,和最新的流程定义的版本号。所以需要查询两类数据:模型 + 流程定义

@Override
    public Page<ModelDTO> page(ModelDTO modelDTO, int page, int pageSize) {
        //从前端传入对象中,获取key和name
        String key = modelDTO.getKey();
        String name = modelDTO.getName();

        //创建模型的查询对象
        ModelQuery modelQuery = repositoryService.createModelQuery()
                .orderByModelName().desc();

        //设置查询条件
        if(StringUtils.isNotEmpty(key)){
            modelQuery.modelKey(key);
        }
        if(StringUtils.isNotEmpty(name)){
            modelQuery.modelName(name);
        }

        //返回查询数量
        long total = modelQuery.count();

        //返回查询结果
        List<Model> list = modelQuery.listPage((page - 1) * pageSize, pageSize);

        //定义分页对象
        Page<ModelDTO> pageResult = new Page(page, pageSize, total);

        //遍历查询结果,返回ModelDTO
        List<ModelDTO> modelDTOList = list.stream().map(item -> {
            ModelDTO dto = new ModelDTO();
            BeanUtils.copyProperties(item, dto);

            //设置流程定义的属性
            //获取流程定义
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(item.getKey())
                    .latestVersion().singleResult();
            if(processDefinition == null){
                dto.setVersion(null);
            }
            else{
                dto.setVersion(processDefinition.getVersion()); //当前部署的流程的版本
                dto.setProcessDefinitionId(processDefinition.getId());//流程定义的id
                dto.setProcessDefinitionSuspended(processDefinition.isSuspended());//流程的状态
            }

            return dto;
        }).collect(Collectors.toList());

        pageResult.setRecords(modelDTOList);

        return pageResult;
    }

3.2.4. 删除

在这里插入图片描述
ModelerController

	/**
     * 删除模型
     */
    @DeleteMapping
    @ApiOperation(value = "删除模型")
    public Result delete(String id){
        modelerService.delete(id);
        return Result.success();
    }

ModelerService:

	/**
     * 删除模型
     * @param id 模型id
     */
    void delete(String id);

ModelerServiceImpl

@Override
    public void delete(String id) {
        repositoryService.deleteModel(id);
    }

3.3. 流程图管理

  • 模型包括基本信息和流程图,流程图相关操作有保存、查看、部署。流程图是符合bpmn2.0规范文件,本质上是一个xml文件。
  • 使用前端组件bpmn.js来设计和展示流程图,在本项目中,对该组件进行了改造。
  • 保存流程图在ModelerService中

3.3.1. 保存

在这里插入图片描述
ModelerController

	/**
     * 保存模型的流程图
     */
    @PostMapping("/xml")
    @ApiOperation("保存流程图")
    public Result<ModelDTO> saveXml(@RequestBody ModelDTO modelDTO){
        log.info("ModelDTO: {}",modelDTO);
        modelerService.saveXml(modelDTO);
        return Result.success(modelDTO);
    }

ModelerService:

	/**
     * 保存流程图
     */
    void saveXml(ModelDTO modelDTO);

ModelerServiceImpl

	@Override
    public void saveXml(ModelDTO modelDTO) {
        //保存模型
        if(StringUtils.isEmpty(modelDTO.getId())){
            String id = this.save(modelDTO);
            modelDTO.setId(id);
        }

        try {
            //保存流程图
            repositoryService.addModelEditorSource(modelDTO.getId(), modelDTO.getContent().getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

3.3.2. 查看

在这里插入图片描述
ModelerService:

	/**
     * 根据模型的id获取流程图
     */
    String getXmlById(String id);

ModelerServiceImpl:

	@Override
    public String getXmlById(String id) {
        byte[] content = repositoryService.getModelEditorSource(id);
        if(content == null){    //新建时
            return "";
        }
        else{
            return new String(content);
        }
    }

ModelerController

	/**
     * 查询流程图的内容
     * @param id
     * @return
     */
    @GetMapping("/xml/{id}")
    @ApiOperation(value = "查询流程图")
    public Result getXmlById(@PathVariable String id){
        log.info("流程图id:{}", id);
        String content = modelerService.getXmlById(id);
        return Result.success(content);
    }

3.3.3. 部署

在这里插入图片描述

  • 将流程模型(流程图)发布、部署到Activiti服务中
  • 部署模型后,生成一个版本的流程定义(ProcessDefinition,数据库表是:ACT_RE_MODEL)

流程部署的传输对象(已导入):

@Data
@ApiModel("部署流程")
public class DeployDTO {

    @ApiModelProperty("模型主键")
    private String modelId;
}

DeployService

package com.itheima.activiti.service.activiti;

public interface DeployService {

    /**
     * 部署模型
     * @param id
     * @return
     */
    void deploy(String id);
}

DeployServiceImpl:

package com.itheima.activiti.service.activiti.impl;import com.itheima.activiti.service.activiti.DeployService;import org.activiti.engine.RepositoryService;import org.activiti.engine.repository.Model;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class DeployServiceImpl implements DeployService {    @Autowired    RepositoryService repositoryService;@Override    public void deploy(String id) {        //根据模型id,获取模型对象        Model model = repositoryService.getModel(id);        //根据模型id,获取模型资源        byte[] content = repositoryService.getModelEditorSource(id);​        //部署模型        repositoryService.createDeployment()                .key(model.getKey())                .name(model.getName())                .addString(model.getName() + ".bpmn20.xml", new String(content))                .deploy();    }}

DeployController:

package com.itheima.activiti.controller.activiti;

import com.itheima.activiti.common.Result;
import com.itheima.activiti.dto.activiti.DeployDTO;
import com.itheima.activiti.service.activiti.DeployService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/deploy")
@Api(tags = "流程部署")
public class DeployController {
    @Autowired
    private DeployService deployService;

    @PostMapping
    @ApiOperation(value="部署", notes = "传入模型id")
    public Result deploy(@RequestBody DeployDTO deployDTO){
        deployService.deploy(deployDTO.getModelId());
        return Result.success();
    }
}

3.4. 流程定义管理

将流程图部署(发布)到activiti引擎后,将会生成流程定义对象(ProcessDefinition),对应的数据库表是:ACT_RE_PROCDEF

3.4.1. 查询

在这里插入图片描述
根据流程定义列表,创建dto对象(已导入):

package com.itheima.activiti.dto.activiti;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@ApiModel("流程定义")
public class ProcessDefinitionDTO {
    @ApiModelProperty("流程定义Id")
    private String id;
    @ApiModelProperty("流程定义名称")
    private String name;
    @ApiModelProperty("流程定义的key")
    private String key;
    @ApiModelProperty("流程定义的版本")
    private Integer version;
    @ApiModelProperty("资源名称bpmn文件")
    private String resourceName;
    @ApiModelProperty("资源名称png文件")
    private String diagramResourceName;
    @ApiModelProperty("部署对象ID")
    private String deploymentId;
    @ApiModelProperty("部署时间")
    private LocalDateTime deploymentTime;
    @ApiModelProperty("挂起状态")
    private Boolean suspended;
}

DeployController:

	@GetMapping("/page")
    @ApiOperation(value = "分页")
    public Result<Page<ProcessDefinitionDTO>> page(ProcessDefinitionDTO processDefinitionDTO,
                                              @RequestParam(required = false, defaultValue = "1") int page,
                                              @RequestParam(required = false, defaultValue = "10") int pageSize) {
        return Result.success(deployService.page(processDefinitionDTO, page, pageSize));
    }

DeployService:

	/**
     * 分页/搜索流程定义
     * @param processDefinitionDTO
     * @param page
     * @param pageSize
     * @return
     */
    Page<ProcessDefinitionDTO> page(ProcessDefinitionDTO processDefinitionDTO, int page, int pageSize);

DeployServiceImpl:

@Override
    public Page<ProcessDefinitionDTO> page(ProcessDefinitionDTO pdDTO, int page, int pageSize) {
        //创建流程定义的查询对象
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();

        //设置查询条件:key、version
        if(StringUtils.isNotBlank(pdDTO.getKey())){
            query.processDefinitionKey(pdDTO.getKey());
        }
        if(null != pdDTO.getVersion()){
            query.processDefinitionVersion(pdDTO.getVersion());
        }

        //分页查询流程定义
        List<ProcessDefinition> list = query.listPage((page - 1) * pageSize, pageSize);

        //返回分页的流程定义dto:复制对象属性、设置部署时间
        List<ProcessDefinitionDTO> pdDtoList = null;
        if(null != list && list.size() > 0){
            //将流程定义转换成dto对象
            pdDtoList = list.stream().map(item ->{
                ProcessDefinitionDTO dto = new ProcessDefinitionDTO();
                //复制对象属性
                BeanUtils.copyProperties(item, dto);

                //查询此流程定义的部署时间
                Deployment deployment = repositoryService.createDeploymentQuery()
                        .deploymentId(item.getDeploymentId())
                        .singleResult();

                //设置dto的部署时间
                dto.setDeploymentTime(LocalDateTime.ofInstant(deployment.getDeploymentTime().toInstant(), ZoneId.systemDefault()));

                return dto;
            }).collect(Collectors.toList());
        }
        //查询总数
        long total = query.count();

        //分页返回dto
        Page<ProcessDefinitionDTO> pageResult = new Page(page, pageSize, total);
        pageResult.setRecords(pdDtoList);

        return pageResult;
    }

3.4.2. 删除

在这里插入图片描述
DeployController:

	@DeleteMapping
    @ApiOperation(value = "删除流程", notes = "流程id")
    public Result delete(@RequestParam List<String> ids) {
        deployService.removeByIds(ids);
        return Result.success("删除成功");
    }

DeployService:

	/**
     * 根据部署id,删除流程定义
     * @param ids:部署id的列表
     */
    void removeByIds(List<String> ids);

DeployServiceImpl:

	@Override
    public void removeByIds(List<String> ids) {
        for (int i = 0; i < ids.size(); i++) {
            repositoryService.deleteDeployment(ids.get(i));
        }
    }

3.4.3. 挂起

挂起时,无法从此流程定义创建流程实例,类似于暂停某个制度的执行。
在这里插入图片描述
DeployController:

	@PutMapping("suspend/{id}")
    @ApiOperation("挂起流程")
    @ApiImplicitParam(name = "id", value = "流程ID", paramType = "query", dataType = "String")
    public Result suspend(@PathVariable("id") String id) {
        deployService.suspend(id);

        return Result.success();
    }

DeployService:

	/**
     * 挂起
     * @param id
     */
    void suspend(String id);

DeployServiceImpl:

	@Override
    public void suspend(String id) {
        repositoryService.suspendProcessDefinitionById(id, true, null);
    }

3.4.4. 激活

在这里插入图片描述
DeployController:

	@PutMapping("active/{id}")
    @ApiOperation("激活流程")
    @ApiImplicitParam(name = "id", value = "流程ID", paramType = "query", dataType = "String")
    public Result active(@PathVariable("id") String id) {
        deployService.active(id);
        return Result.success();
    }

DeployService:

	/**
     * 激活
     * @param id
     */
    void active(String id);

**

	/**
     * 激活
     * @param id
     */
    void active(String id);

DeployServiceImpl:

	@Override
    public void active(String id) {
        repositoryService.activateProcessDefinitionById(id, true, null);
    }

3.5. 下载流程图

查看下载流程图功能比较复杂,代码供参考,不做开发要求。

核心实现类是ActivitiProcessDiagramCanvas.java和ActivitiProcessDiagramGenerator.java,需要提前导入代码文件夹中的diagram包。

3.5.1. 下载文件

在这里插入图片描述
DeployController:

@GetMapping(value = "resource")
    @ApiOperation("获取资源文件")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deploymentId", value = "部署ID", paramType = "query", dataType="String"),
            @ApiImplicitParam(name = "resourceName", value = "资源名称", paramType = "query", dataType="String")
    })
    public void resource(String deploymentId, String resourceName, @ApiIgnore HttpServletResponse response) throws Exception {
        InputStream resourceAsStream = deployService.getResourceAsStream(deploymentId, resourceName);

        IOUtils.copy(resourceAsStream, response.getOutputStream());
    }

DeployService:

	/**
     * 获取流程资源,返回数据流
     * @param deploymentId
     * @param resourceName
     * @return
     */
    InputStream getResourceAsStream(String deploymentId, String resourceName);

DeployServiceImpl:

	@Override
    public InputStream getResourceAsStream(String deploymentId, String resourceName) {
        InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, resourceName);

        return resourceAsStream;
    }

3.5.2. 下载图片
在这里插入图片描述
DeployController:

	@GetMapping(value = "svg")
    @ApiOperation("获取图片文件")
    public void svg(String deploymentId,@ApiIgnore HttpServletResponse response) throws Exception {
        InputStream resourceAsStream = deployService.svg(deploymentId);

        response.setHeader("Content-Type", "image/svg+xml");
        response.setHeader("Cache-Control", "no-store, no-cache");

        IOUtils.copy(resourceAsStream, response.getOutputStream());
    }

DeployService:

	/**
     * 获取流程图片
     * @param deploymentId
     * @return
     */
    InputStream svg(String deploymentId);

DeployServiceImpl:

@Override
    public InputStream svg(String deploymentId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());

        ProcessDiagramGenerator diagramGenerator = new ActivitiProcessDiagramGenerator();

        InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, new ArrayList<>());

        return inputStream;
    }

总结

  1. 基本概念
    • 流程模型、流程定义
    • 流程模型和流程定义的操作
    • 开发流程
  2. 流程模型的基本操作
    • 保存、分页查询、删除
  3. 流程图的操作
    • 保存、查看、部署
  4. 流程定义的操作
    • 查询、删除、挂起和激活
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值