Day01 流程中心概述

学习目标:

  • 能够熟练掌握如何使用流程中心系统
  • 能够说出项目的应用场景、核心架构
  • 能够说出工作流的应用场景、常见的工作流引擎
  • 能够熟练掌握Activiti的核心API和入门案例
  • 能够熟练设计流程图
  • 能够熟练完成案例代码的开发
  • 能够熟悉核心服务、表、对象等及相互关系

文章目录

  • Day01 流程中心概述
    • 学习目标:
  • 1. 项目概述
    • 1.1. 项目背景
    • 1.2. 系统架构
      • 1.2.1 功能清单
      • 1.2.2 核心概念
      • 1.2.3 系统结构
      • 1.2.4 开发重点
  • 2. Activiti入门案例
    • 2.1 Activiti基础
      • 2.1.1 核心概念
      • 2.1.2 核心API
      • 2.1.3 表结构
    • 2.2 案例准备
      • 2.2.1 案例介绍
      • 2.2.3 创建工程
      • 2.2.4 设计流程
    • 2.3 案例代码
      • 2.3.1 保存模型
      • 2.3.2 保存流程图
      • 2.3.3 部署模型
      • 2.3.4 查询流程定义
      • 2.3.5 启动实例
      • 2.3.6 完成任务
      • 2.3.7 查询历史
  • 3. 今日总结
    • 3.1. 基本概念
    • 3.2. Activiti核心API和表
    • 3.3 Activiti入门案例
  • 番外 idea绘制流程图出现中文乱码怎么办?
    • 修改idea配置
    • 修改idea bin下的vmprotions文件
    • 修改idea中的enconding
    • 重启

1. 项目概述

1.1. 项目背景

请假是日常学习、工作中非常常见的一个场景,比如在学校中,小智因为生病,需要请假一天,他给班主任打个电话,说要请一天假。班主任同意后,小智的行为不会构成无故旷课。工作中的请假也是一样。请假也会包含比较复杂的情况,比如请一天假和请十天假,需要的审批流程和审批人员可能不同。

企业中请假一般会和个人假期、工资等挂钩,因此需要对请假过程进行”留痕“处理,具体做法是:员工需要填写一个请假条,写明请假的请假人、时间、缘由等,甚至需要附加证明材料,然后找各级领导进行审批,他的直接领导、领导的领导在上边签字同意,证明不是旷工。

如下图是一个企业中的请假流程:

如果公司规模比较小,可以使用口头请假、纸质请假单,但是当公司达到一定规模时,为了考勤统计、绩效考核、请假证明等原因,需要一个软件系统,用来记录所有员工的请假,员工在使用这个系统时,大致是这样的过程或步骤:

  • 员工提交请假单
  • 领导审批
  • 必要时需要二级、三级领导审批
  • 需要通知人事部门,用于考勤和工资计算

这个过程叫做工作流,工作流简单的讲就是工作的流动,是多个人协作完成一项工作。需要注意的是,在工作流中会涉及到多个角色,每个角色完成不同的任务。

工作流的场景非常多,几乎可以说无处不在,常见工作流场景:

  • 政府企业的公文流转、项目申报、公司注册、税务减免
  • 银行贷款的申请、信用卡申请
  • 企业管理中的请假、财务报销、人员招聘、调薪、奖金发放、合同续签
  • 电商系统中的退货、售后、退款、下单
  • 物流仓储中的出库、入库、运输等

工作流的场景虽然非常多,但是开发的过程确是大同小异。我们来看一个工作流系统的整体结构:

从上图我们可以看到,一个工作流大致包含三部分:

  • 业务:不同的业务流程有不同的业务单据,比如请假单和报销单,里边的属性字段是不一样的
  • 人员:企业或组织中的人员,涉及到人员不同的部门、岗位和角色等
  • 流程:这是一个公共的部分,涉及到如何设计流程、流程如何运转、如何查看运转的历史等

今天要学习的流程审批中心,就是以请假流程的开发为例,系统讲解如何开发一个工作流审批系统,只要掌握了这个系统的开发,以后开发其他业务的审批系统都是相同的过程。

1.2. 系统架构

1.2.1 功能清单

1.2.2 核心概念


3.工作流引擎:来开发工作流转的框架,是可重用的软件代码。

1.2.3 系统结构


进一步细化:

1.2.4 开发重点

一个工作流系统大致包含以下模块,重点和点是审批模块的开发。幸运的是,工作流引擎正是为了解决这部分难点的。

如下图所示,有了工作流引擎,我们的开发重点是:业务表单和用户操作。

流程审批中心基于最新的Activiti7工作流引擎开发,下面我们首先要学习一下Activiti7的相关知识,通过对入门案例的编写,深刻理解工作流中的一些概念、掌握工作流的开发步骤和方法。

2. Activiti入门案例

2.1 Activiti基础

2.1.1 核心概念

如果要学习一门技术,首先要掌握这门技术相关的一些概念。

下图以生活中的请假为例,对比了工作流和生活中请假过程的一些概念。

2.1.2 核心API

Activiti作为一个框架,提供了一些API,以便于我们开发使用。

Service是Activiti引擎提供用于进行工作流部署、执行、管理的服务接口,我们使用这些接口可以就是操作服务对应的数据表。

2.1.3 表结构

2.2 案例准备

2.2.1 案例介绍

请假的业务,是现实生活中非常常见的一个业务,主要包括当事人提交请假,他的直属领导,或更高层的领导来逐个进行审批,最后完成一个请假的过程。每个公司的请假流程细节上可能存在差异,但总体流程都差不多。下面我们一起来看一个简版的请假流程,如下:

  • 当事人发起请假申请
  • 领导审批,通过或者拒绝

    实现步骤:

2.2.3 创建工程

  • 创建数据库
  • 创建maven工程:itcast-workflow
  • 创建resources目录
  • 导入pom.xml文件内容
  • 导入application.yml文件内容
  • 启动类
  • UserDetailService实现类
  • 测试类
  1. 数据库脚本
create database itcast_workflow default charset utf8mb4;
<?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><parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.5.0</version></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><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></dependency><dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter</artifactId><version>7.1.0.M6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

3.application.yml

server:port: 8090spring:datasource:url: jdbc:mysql://localhost:3306/itcast_workflow?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=trueusername : rootpassword : rootdriver-class-name: com.mysql.jdbc.Driveractiviti:#1.flase:默认值。activiti在启动时,对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常#2.true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建#3.create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)#4.drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)database-schema-update: true#检测历史表是否存在 activiti7默认没有开启数据库历史记录 启动数据库历史记录db-history-used: true#记录历史等级 可配置的历史级别有none, activity, audit, full#none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。#activity:级别高于none,保存流程实例与流程行为,其他数据不保存。#audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。#full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。history-level: full#校验流程文件,默认校验resources下的processes文件夹里的流程文件check-process-definitions: false#默认采用UUID作为主键, 设置为false, 将采用整型主键use-strong-uuids: false#关闭springAutoDeployment自动部署流程定义deployment-mode:never-faillogging:level:org.activiti.engine.impl.persistence.entity: debug

注意事项:

Mysql 设置区分大小写:- 修改配置文件my.ini(linux是my.cnf文件),在[mysqld] 后面添加:lower_case_table_names=2- 注意:- 5.61---表示不区分大小写 2---表示区分大小写- 5.71---表示不区分大小写 0---表示区分大小写

4.启动类

package com.itheima.activiti;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
  1. UserDetailServiceImpl

Activiti默认集成SpringSecurity安全框架,需要创建UserDetailsService的一个实现类

package com.itheima.activiti.auth;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.Service;@Servicepublic class UserDetailServiceImpl implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {return null;}}

环境准备好了之后,就可以直接运行启动类,下图中的表会自动被创建(注意:连接的数据库需要自己创建,数据库不会自动创建),Activiti7中自带的数据库表共25张。

数据库表

看到程序运行之后自动创建的表,我们发现Activiti 的表都以 ACT_ 开头。

第二部分是表示表的用途的两个字母标识。 用途也和服务的 API 对应。

表结构说明:

6.测试类

package com.itheima.activiti.test;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class ActivitiTest {}

在测试类中开发案例代码。

2.2.4 设计流程

  1. 流程设计器

使用activiti工作流比较重要的一步就是绘制流程图。最方便的方法就是使用Idea中的插件(actiBPM)进行绘制,叫做离线流程设计器。

与离线流程设计器对应的是在线流程设计,我们将在第二天的课程中介绍

顾名思义,在线流程设计器的作用是通过web线上直接设计流程,在线上环境下,可以直接保存和部署。

安装方式如下:

1). 在线安装
Settings –> Plugins —–> Marketable ———> 搜索 actiBPM

安装完成之后,重新启动IDEA 。

**注意: IDEA 2019.1.4之后的版本,无法在线安装此插件 **
https://plugins.jetbrains.com/plugin/7429-actibpm/versions

2). 离线安装

部分版本的IDEA在Martketplace中搜索不到 actiBPM , 这个时候就选择离线安装 ;
2. 设计请假流程

鼠标右键,选择 “BpmnFile”,创建一个流程图,然后就可以开启绘制。

打开流程设计器,拖动BPMN中的组件,开始绘制。

2.3 案例代码

/**
* 1、保存模型
* 2、保存流程图
* 3、部署模型
* 4、查询流程定义
* 5、启动流程
* 6、执行任务
* 7、查询历史
*/

2.3.1 保存模型

Activit的模型包含两部分,Model和流程图(文件),本案例保存模型

@AutowiredRepositoryService repositoryService;/** * 保存模型对象 */@Testpublic void saveModel(){//创建activiti模型对象Model model = repositoryService.newModel();model.setKey("myKey");model.setName("测试保存模型");//保存流程模型repositoryService.saveModel(model);}

流程模型保存在ACT_RE_MODEL表中。

2.3.2 保存流程图

Activit的模型包含两部分,Model和流程图(文件),本案例保存流程图

/** * 保存流程图 */@Testpublic void testSaveBpmn() throws IOException {File file = new File("src/main/resources/holiday.bpmn");byte[] bytes = FileUtils.readFileToByteArray(file);repositoryService.addModelEditorSource("15001", bytes);}

流程图保存在ACT_GE_BYTEARRAY表中:

2.3.3 部署模型

通常情况下,一些流程是提前规定好的(比如我们的请假流程),此时我们可以提前在我们的流程设计器中将流程先设计出来,再将已设计好的流程定义文件部署到 activti流程引擎中。

/** * 部署流程 */@Testpublic void testDeployment(){repositoryService.createDeployment().key("mykey").name("简易请假流程").addClasspathResource("holiday.bpmn").deploy();}

查询流程部署数据:

1). ACT_RE_PROCDEF:已部署的流程定义

  • 流程部署后,将会创建流程定义(ProcessDefination),
  • 相同key的流程部署后,将会创建一个流程的不同的流程定义,即该流程的不同版本。
  • 2). ACT_RE_DEPLOYMENT:部署单元信息

3). ACT_GE_BYTEARRAY:通用的流程定义和流程资源

2.3.4 查询流程定义

对于一个流程图,只要key相同,每部署一次将会生成一个流程定义。即一个流程可以有多个流程定义。

/** * 查询流程定义 */@Testpublic void testProcessDef(){List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myProcess_1").list();for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i).getId());}ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myProcess_1").latestVersion().singleResult();System.out.println(processDefinition.getId());}

2.3.5 启动实例

一个流程部署后,生成流程定义,我们可以根据流程定义,发起流程。

  • 发起流程时,依据的是流程定义里的key,这个key就是流程图中的id:myProcess_1。
  • 发起流程是运行时服务对象创建了一个流程实例。
  • 发起流程后,流程会往下走一步,进入到请假申请。

    代码如下:
/** * 启动实例 */@Autowiredprivate RuntimeService runtimeService;@Testpublic void testStart(){runtimeService.startProcessInstanceByKey("myProcess_1");}

1)ACT_RU_EXECUTION:运行时流程执行实例

2)ACT_RU_TASK:运行时任务

3)ACT_HI_PROCINST: 历史的流程实例

4)ACT_HI_ACTINST:历史的活动实例

5)ACT_HI_TASKINST:历史的任务实例

2.3.6 完成任务

同样完成任务我们首先就要得到我们用来完成任务的服务类,我们是根据运行时任务表当中的id来完成的。

1). 完成第一步任务

当我们完成当前任务(请假申请),流程就会进入到领导审批。
具体代码如下, task id是ACT_RU_TASK的主键:

/** * 执行任务 */@Autowiredprivate TaskService taskService;@Testpublic void testComplete(){taskService.complete("7505");}

执行完成后:

同样完成领导审批任务(ACT_RU_TASK):

2). 完成第二步任务
当完成当前任务(领导审批)之后,该流程就结束了,流程结束,数据库表 ACT_RU_TASK 中的数据就会被删除。

@Testpublic void testComplete(){taskService.complete("10002");}

2.3.7 查询历史

我们可以通过API, 查询当前指定用户, 待处理的任务 ;

/** * 查询流程历史 * */@AutowiredHistoryService historyService;@Testpublic void testHistory(){ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myProcess_1").latestVersion().singleResult();List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processDefinitionId(processDefinition.getId()).list();for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i).getActivityName());}}


Activiti历史信息很丰富,经常用的是以下几个:

  • 活动
  • 实例
  • 任务
  • 变量

3. 今日总结

3.1. 基本概念

  • 工作流、工作流引擎、常见工作流引擎
  • 流程图、节点、活动、模型、部署、流程定义、流程实例、流程任务
  • 流程图的结构

3.2. Activiti核心API和表

4个核心API,25张表

3.3 Activiti入门案例

  1. 搭建项目:

    maven工程、pom文件、yml文件、创建数据库、Springboot启动类

  2. 开发过程:

    设计流程、保存模型和流程图、部署流程、启动实例、执行任务、查看历史

番外 idea绘制流程图出现中文乱码怎么办?

  • 第一步 修改idea配置
  • 第二步 修改idea bin目录下的文件
  • 第三步 xi

修改idea配置

点开后的文件添加以下内容:-Dfile.encoding=UTF-8

修改idea bin下的vmprotions文件


修改idea中的enconding

File -> settings -> Editor -> Enconding

重启

能看见如下图显示就说明成功了