工作流介绍
概念
工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。
具体应用
- 关键业务流程:订单、报价处理、合同审核、客户电话处理、供应链管理等
- 行政管理类:出差申请、加班申请、请假申请、用车申请、各种办公用品申请、购买申请、日报、周报等凡是原来手工流转处理的行政表单。
- 人事管理类:员工培训安排、绩效考评、职位变动处理、员工档案信息管理等。
- 财务相关类:付款请求、应收款处理、日常报销处理、出差报销、预算和计划申请等。
- 客户服务类:客户信息管理、客户投诉、请求处理、售后服务管理等。
- 特殊服务类: ISO 系列对应流程、质量管理对应流程、产品数据信息管理、贸易公司报关处理、物流公司货物跟踪处理等各种通过表单逐步手工流转完成的任务均可应用工作流软件自动规范地实施。
案例说明
案例:出差费用报销
目标:公司把出差费用转账到自己的账户中。
参与人:申请人、部门主管、总经理、财务。
什么是工作流引擎
是一种按照预定义规则【需要符合BPMN规范】进行部署,将业务和节点的流程进行分离【特定形式进行关联】,实现节点的自动流转的工作流框架。
- 需要将预定于的流程文件BPMN部署到工作流引擎中,会把节点路径信息存储到数据库中
- 工作流引擎提供了大量的API对流程进行查询处理,细节都是对应用程序屏蔽的,大大提供开发效率
- 业务逻辑的处理和流程的流转是分离的,是通过BusinessKey进行关联的。
什么是Activity7
概述
- Alfresco 软件在 2010 年 5 月 17 日宣布 Activiti 业务流程管理(BPM)开源项目的正式启动, 其首席架构师由业务流程管理 BPM 的专家 Tom Baeyens 担任, Tom Baeyens 就是原来 jbpm 的架构师,而 jbpm 是一个非常有名的工作流引擎,当然 activiti 也是一个工作流引擎。
- Activiti是一个工作流引擎, Activiti 可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言(BPMN2.0)进行定义,业务系统按照预先定义的流程进行执行,实现了业务系统的业务流程由 Activiti 进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
官方网站: https://www.Activiti.org/
内部核心机制
- 业务流程图要规范化,需要遵守一套标准。
- 业务流程图本质上就是一个XML文件,而XML可以存放所要的数据。
- 读取业务流程图的过程就是解析XML文件的过程。
- 读取一个业务流程图的结点就相当于解析一个XML的结点,进一步将数据插入到MySQL表中,形成一条记录。
- 将一个业务流程图的所有节点都读取并存入到MySQL表中。
- 后面只要读取MySQL表中的记录就相当于读取业务流程图的一个节点。
- 业务流程的推进,后面就转换为读取表中的数据,并且处理数据,结束的时候这一行数据就可以删除了。
BPMN
- BPMN(Business Process Model And Notation),业务流程模型和符号,是由BPMI(Business Process Management Initiative)开发的一套的业务流程建模符号,使用BPMN提供的符号可以创建业务流程。2004年5月发布了BPMN1.0规范。BPMI于2005年9月并入OMG(The Object Management Group,对象管理组织)组织。OMG于2011年1月发布BPMN2.0的最终版本。
- Activit 就是使用 BPMN2.0 进行流程建模、流程执行管理,它包括很多的建模符号。
一个BPMN的例子:
- 当事人填写请假单,启动流程后吧请教单ID 绑定到流程中;
- 部门经理对请假单进行审核;
- 然后人事经理进行复核并进行备案;
- 最后请假流程结束。
- BPMN其实是用XML表示业务流程的,上变的图片就是.bpmn文件使用文本编辑器打开。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" 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:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1620716847764" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="leave" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="StartEvent"/>
<userTask activiti:candidateUsers="lisi,wangwu" activiti:exclusive="true" id="_4" name="部门经理审批"/>
<userTask activiti:assignee="rose" activiti:exclusive="true" id="_6" name="人事复批"/>
<endEvent id="_7" name="EndEvent"/>
<sequenceFlow id="_12" sourceRef="_6" targetRef="_7"/>
<sequenceFlow id="_13" sourceRef="_2" targetRef="_4"/>
<sequenceFlow id="_14" sourceRef="_4" targetRef="_6"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="leave">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="175.0" y="185.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<omgdc:Bounds height="55.0" width="85.0" x="245.0" y="175.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<omgdc:Bounds height="55.0" width="85.0" x="380.0" y="175.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
<omgdc:Bounds height="32.0" width="32.0" x="505.0" y="185.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_2" targetElement="_4">
<omgdi:waypoint x="207.0" y="201.0"/>
<omgdi:waypoint x="245.0" y="202.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_7">
<omgdi:waypoint x="465.0" y="202.5"/>
<omgdi:waypoint x="505.0" y="201.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_14" id="BPMNEdge__14" sourceElement="_4" targetElement="_6">
<omgdi:waypoint x="330.0" y="202.5"/>
<omgdi:waypoint x="380.0" y="202.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
Activity7如何使用
部署 Activiti
Activiti是一个工作流引擎(其实就是一堆 jar 包 API),业务系统使用 Activiti来对系统的业务流程进行自动化管理,为了方便业务系统访问(操作)Activiti的接口或功能,通常将 Activiti环境与业务系统的环境集成在一起。
流程定义
使用 Activiti流程建模工具(Activiti-designer)定义业务流程(.bpmn 文件) 。bpmn 文件就是业务流程定义文件,通过 xml 定义业务流程。
如果使用其它公司开发的工作引擎一般都提供了可视化的建模工具(Process Designer)用于生成流程定义文件,建模工具操作直观,一般都支持图形化拖拽方式、 多窗口的用户界面、 丰富的过程图形元素、过程元素拷贝、粘贴、删除等功能。
流程定义部署
向 Activiti部署业务流程定义(.bpmn 文件)。使用 Activiti提供的 api 向 Activiti 中部署.bpmn 文件(一般情况还需要一块儿部署业务流程的图片.png)
启动一个流程实例(ProcessInstance)
启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程的执行互相不影响,就好比定义一个 java 类,实例化两个对象一样,部署的流程就好比 java 类,启动一个流程实例就好比 new 一个 java 对象。
用户查询待办任务(Task)
因为现在系统的业务流程已经交给 Activiti管理,通过 Activiti就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些 Activiti帮我们管理了,而不像上边需要我们在 sql语句中的where条件中指定当前查询的状态值是多少。
用户办理任务
用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如采购单创建后由部门经理审核,这个过程也是由 Activiti帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了。
流程结束
当任务办理完成没有下一个任务结点了,这个流程实例就完成了。
Activity7 入门案例
创建Springboot项目
添加相关依赖
<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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
</dependencies>
注意:本项目我们使用是 7.0.0.Beta1版本,如果想使用 7.0.0.GA版 要求jdk为11版本。否则会报类文件具有错误的版本55.0,应为52.0
。
添加核心配置文件
- 需要在resource目录中添加配置文件 activiti-cfg.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti7?nullCatalogMeansCurrent=true"/>
<property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUsername" value="root"/>
<property name="jdbcPassword" value="123456"/>
<property name="databaseSchemaUpdate" value="true"/>
<property name="asyncExecutorActivate" value="false"/>
<property name="mailServerHost" value="mail.my-corp.com"/>
<property name="mailServerPort" value="5025"/>
</bean>
</beans>
获取 ProcessEngine 对象
默认的方式
public class SpringBootActivityApplicationTests {
/**
* 第一种方式:获取 ProcessEngine 对象
*/
@Test
public void test1() {
// 通过 getDefaultProcessEngine 方法获取流程引擎对象,会加载resources 目录下的 activiti.cfg.xml
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
System.out.println(processEngine);
}
}
注意:如果启动报如下错误,只需要爱mysql的连接字符串中添加上 ?nullCatalogMeansCurrent=true,设置上只查当前连接的schema库即可。
编程方式获取
上面配置文件方式是一种Spring配置文件,但是这并不意味着只能用于Spring环境,我们也可以通过编程的方式来使用,从而来构建 ProcessEngineConfiguration 对象,具体的实线如下:
/**
* 第二种方式:基于Java代码获取 ProcessEngine 对象
*/
@Test
public void test2() {
ProcessEngine processEngine = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration()
.setJdbcDriver("jdbc:mysql://localhost:3306/activiti7?nullCatalogMeansCurrent=true")
.setJdbcUrl("com.mysql.cj.jdbc.Driver")
.setJdbcUsername("root")
.setJdbcPassword("123456")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)//设置自动维护表
.buildProcessEngine();
System.out.println(processEngine);
}
上面属性说明:
databaseSchemaUpdate:用于设置流程引擎启动关闭时使用的数据库结构控制策略。
- false:(默认)当引擎启动时,检查数据库表结构的版本是否匹配库文件版本。版本不匹配时抛出异常。
- true:构建引擎时,检查并在需要时更新表结构。表结构不存在则会创建。
- create-drop:引擎创建时创建表结构,并在引擎关闭时删除表结构。
Activiti支持的数据库:
Activiti 的运行需要数据库支撑,需要安装 Activiti数据库,支持如下版本:
数据库类型 | JDBC URL 实例 | 备注 |
---|---|---|
h2 | jdbc:h2:tcp://localhost/Activiti | 默认配置的数据库 |
mysql | jdbc:mysql://localhost:3306/Activiti?autoReconnect=true | 使用 mysql-connector-java驱动测试 |
oracle | jdbc:oracle:thin:@localhost:1521:xe | |
postgres | jdbc:postgresql://localhost:5432/Activiti | |
db2 | jdbc:db2://localhost:50000/Activiti | |
mssql | jdbc:sqlserver://localhost:1433/Activiti |
数据库表命名规则
Activiti 的表都是以 ACT_ 开头。第二部分是表示表的用途的两个字母标识。用途也和服务的API对应。
- ACT_RE_*:'RE’表示Repository。这个前缀的表包含了流程定义和流程静态资源(图片、规则等等)。
- ACT_RU_*:'RU’表示Runtime。这些运行时的表,包含流程实例,任务、变量,异步任务等运行中的数据。Activiti只在流程实例执行过程中保存这些数据,在流程结束时就会删除这些记录。这些运行时表可以一直很小并且速度很快。
- ACT_HI_*:'HI’表示History。这些表包含历史数据,比如历史流程实例,变量,任务等。
- ACT_GE_*:'GE’表示General。通用数据,用于不同场景下。
流程引擎API
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
这行代码默认是读取resource目录下的 activiti.cfg.xml
文件,这个文件本质上就是spring的配置文件,加载之后会读取配置文件中id名为processEngineConfiguration
的bean,通过这个配置对象可以获取到流程引擎对象ProcessEngine。
- RepositoryService,是Activiti的资源管理接口,提供了管理和控制流程发布包和流程定义的操作。使用工作流建模工具设计的业务流程图需要使用此Service将流程定义文件的内容部署到计算机中。
- RuntimeService,是Activiti的流程运行管理接口,可以从这个接口中获取很多关于流程执行相关的信息。
- TaskService,是Activiti的任务管理接口,可以从这个接口中获取任务的信息。
- HistoryService,是Activiti的历史管理类,可以查询历史信息,执行流程时,引擎会包含很多数据(根据配置),比如流程实例启动时间,任务的参与者,完成任务的时间,每个流程实例的执行路径,等等。
- ManagementService,是Activiti的引擎管理接口,提供了对Activiti流程引擎的管理和维护功能,这些功能不在工作流驱动的应用程序中使用,主要用于Activiti系统的日常维护。
流程设计器
我们采用Activity6 官网提供的流程设计器来实现一个简单流程的设计。然后完成相关的部署和流程整体操作。
官网下载:https://www.activiti.org/get-started
将下载好的文件进行解压,进入到wars中。提供的有 Activiti-app.war,将这个war包拷贝到Tomcat服务器中即可。
注意:Tomcat的版本不要高于 8.5,然后启动Tomcat服务。
访问地址:http://localhost:8080/activiti-app 即可。用户名/密码:admin/test
绘制流程图
流程需求:开始->人事审批(zhangsan)->经理审批(tom)->结束。
点击 create process 弹出窗口。录入相关的流程定义信息。
对应节点指定审批人。
绘制好流程图后,保存并下载对应的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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" 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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
<process id="固定用户的入门案例" name="test1" isExecutable="true">
<documentation>test1</documentation>
<startEvent id="sid-F8220B5F-445A-47F7-9960-E15EFBBC6340"></startEvent>
<userTask id="sid-BAD268F7-3D4E-4E08-97F8-2E9639ABD72A" name="人事审批" activiti:assignee="zhangsan">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<userTask id="sid-4D0BD1B9-4569-41D3-B403-61BD189E724B" name="经理审批" activiti:assignee="tom">
<extensionElements>
<modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
</extensionElements>
</userTask>
<endEvent id="sid-24C7EB1C-E0AB-42F4-A022-AFA2370A6E21"></endEvent>
<sequenceFlow id="sid-DF8137D1-9627-4722-BFC2-CF5B223F2089" sourceRef="sid-F8220B5F-445A-47F7-9960-E15EFBBC6340" targetRef="sid-BAD268F7-3D4E-4E08-97F8-2E9639ABD72A"></sequenceFlow>
<sequenceFlow id="sid-5B38CC54-EDBE-4ACA-8D33-0536F827C9BA" sourceRef="sid-BAD268F7-3D4E-4E08-97F8-2E9639ABD72A" targetRef="sid-4D0BD1B9-4569-41D3-B403-61BD189E724B"></sequenceFlow>
<sequenceFlow id="sid-FA1365B6-A08D-43B4-AB6E-772016756378" sourceRef="sid-4D0BD1B9-4569-41D3-B403-61BD189E724B" targetRef="sid-24C7EB1C-E0AB-42F4-A022-AFA2370A6E21"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_test1">
<bpmndi:BPMNPlane bpmnElement="test1" id="BPMNPlane_test1">
<bpmndi:BPMNShape bpmnElement="sid-F8220B5F-445A-47F7-9960-E15EFBBC6340" id="BPMNShape_sid-F8220B5F-445A-47F7-9960-E15EFBBC6340">
<omgdc:Bounds height="30.0" width="30.0" x="56.39999283254157" y="134.99999776482585"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-BAD268F7-3D4E-4E08-97F8-2E9639ABD72A" id="BPMNShape_sid-BAD268F7-3D4E-4E08-97F8-2E9639ABD72A">
<omgdc:Bounds height="80.0" width="100.0" x="166.39999067187324" y="112.99999772012237"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-4D0BD1B9-4569-41D3-B403-61BD189E724B" id="BPMNShape_sid-4D0BD1B9-4569-41D3-B403-61BD189E724B">
<omgdc:Bounds height="80.0" width="100.0" x="344.99999485909944" y="112.99999603629121"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sid-24C7EB1C-E0AB-42F4-A022-AFA2370A6E21" id="BPMNShape_sid-24C7EB1C-E0AB-42F4-A022-AFA2370A6E21">
<omgdc:Bounds height="28.0" width="28.0" x="524.9999921768905" y="138.99999564886102"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="sid-FA1365B6-A08D-43B4-AB6E-772016756378" id="BPMNEdge_sid-FA1365B6-A08D-43B4-AB6E-772016756378">
<omgdi:waypoint x="444.99999485909944" y="152.99999590176685"></omgdi:waypoint>
<omgdi:waypoint x="524.9999921768905" y="152.99999568652785"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-5B38CC54-EDBE-4ACA-8D33-0536F827C9BA" id="BPMNEdge_sid-5B38CC54-EDBE-4ACA-8D33-0536F827C9BA">
<omgdi:waypoint x="266.39999067187324" y="152.99999724872507"></omgdi:waypoint>
<omgdi:waypoint x="344.99999485909944" y="152.9999965076885"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="sid-DF8137D1-9627-4722-BFC2-CF5B223F2089" id="BPMNEdge_sid-DF8137D1-9627-4722-BFC2-CF5B223F2089">
<omgdi:waypoint x="86.39678339914812" y="150.31027619034185"></omgdi:waypoint>
<omgdi:waypoint x="166.39999067187324" y="151.96551496150167"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
然后我们就可以做流程部署操作了。
流程操作
流程部署
将下载好的 test1.bpmn20.xml
文件拷贝到 resources/flow
文件夹下。
/**
* 流程部署操作
*/
@Test
public void test3() {
// 1.获取 processEngine 对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2.获取 RepositoryService 对象
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3.使用 RepositoryService 对象完成流程部署
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("flow/test1.bpmn20.xml")
.name("第一个流程")
.deploy();// 是流程部署的行为,可以部署多个流程定义
System.out.println("流程部署ID:" + deploy.getId());
System.out.println("流程部署名称:" + deploy.getName());
}
流程部署的行为涉及到数据库中的表:
- act_re_deployment:流程部署表,一次部署的行为产生的表
- act_re_procdef:流程定义表,流程图对应的表
- act_ge_bytearray:二进制资源表
- act_ge_property:引擎属性表
然后我们可以通过 Activiti 提供的相关API 来获取流程部署和流程定义的相关信息。
/**
* 查询当前部署的流程有哪些
*/
@Test
public void test4() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
// 查询部署相关信息
List<Deployment> list = repositoryService.createDeploymentQuery().list();
for (Deployment deployment : list) {
System.out.println("流程部署ID:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
// 查询部署流程的定义信息
List<ProcessDefinition> list1 = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition definition : list1) {
System.out.println("流程定义ID:"+definition.getId());
System.out.println("流程定义名称:"+definition.getName());
System.out.println("流程定义key:"+definition.getKey());
System.out.println("流程定义版本:"+definition.getVersion());
System.out.println("流程部署ID:"+definition.getDeploymentId());
System.out.println("====================");
}
}
发起流程
部署流程成功后,我们可以发起一个流程。发起流程,需要通过 RuntimeService
来实现。
/**
* 发起一个流程
*/
@Test
public void test5() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 发起流程,需要通过 runtimeService 来实现
RuntimeService runtimeService = processEngine.getRuntimeService();
// 通过流程定义 ID 来启动流程,返回的是流程实例对象
ProcessInstance processInstance = runtimeService.startProcessInstanceById("test1:1:3");
System.out.println("流程定义的ID = " + processInstance.getProcessDefinitionId());
System.out.println("流程实例的ID = " + processInstance.getId());
}
发起流程成功后,在对应的ACT_RU_TASK
表中有一条对应的代办记录。(此时处于zhangsan代办任务中)
涉及到的相关表:
- act_hi_taskinst:历史任务表
- act_hi_procinst:历史流程实例表,发起一个流程创建的表
- act_hi_actinst:历史活动信息表,流程审批节点的记录信息
- act_hi_identitylink:历史身份连接表
- act_ru_exection:运行时执行实例表
- act_ru_task:运行时任务表,当前需要审批记录表,节点审批通过后就会被删除
- act_ru_identitylink:运行时身份连接表
查询流程
用户登录后查询代办的任务信息,我们需要通过TaskService
来实现查询操作,具体代码如下:
/**
* 代办任务查询
*/
@Test
public void test6() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 执行中的人物处理通过 taskService 来实现
TaskService taskService = processEngine.getTaskService();
// task 对象对应其实就是 act_ru_task 这张表的记录
List<Task> list = taskService.createTaskQuery().taskAssignee("zhangsan").list();
for (Task task : list) {
System.out.println("流程定义id = " + task.getProcessDefinitionId());
System.out.println("流程实例id = " + task.getProcessInstanceId());
System.out.println("任务id = " + task.getId());
System.out.println("任务名称 = " + task.getName());
}
}
审批流程
当前登录用户查看到相关的代办任务信息,选择任务进行处理,完成流程的审批处理。
/**
* 任务审批,并添加意见
*/
@Test
public void test7() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
// 根据当前登录用户查询出对应的代办任务
List<Task> taskList = taskService.createTaskQuery()
.taskAssignee("tom").list();
for(Task task:taskList){
//在任务执行之前任务添加批注信息
taskService.addComment(task.getId(),task.getProcessInstanceId(),task.getName()+"审批通过");
// 做对应的任务审批处理
taskService.complete(task.getId());
}
// 完成任务
// taskService.complete("2505");
}
查看历史记录
/**
* 查询历史记录
*/
@Test
public void test8() {
//流程实例ID
String processInstanceId = "2501";
//任务审核人
String taskAssignee = "zhangsan";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取historyService
HistoryService historyService = processEngine.getHistoryService();
//获取taskService
TaskService taskService = processEngine.getTaskService();
//获取历史审核信息
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().activityType("userTask")//只获取用户任务
.processInstanceId(processInstanceId).taskAssignee(taskAssignee).finished().list();
for (HistoricActivityInstance instance : list) {
System.out.println("任务名称:" + instance.getActivityName());
System.out.println("任务开始时间:" + instance.getStartTime());
System.out.println("任务结束时间:" + instance.getEndTime());
System.out.println("任务耗时:" + instance.getDurationInMillis());
//获取审核批注信息
List<Comment> taskComments = taskService.getTaskComments(instance.getTaskId());
if (taskComments.size() > 0) {
System.out.println("审批批注:" + taskComments.get(0).getFullMessage());
}
}
}
删除流程
/**
* 流程定义删除
*/
@Test
public void test9() {
//流程部署Id
String deploymentId = "10001";
//创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取仓库服务
RepositoryService repositoryService = processEngine.getRepositoryService();
//删除流程定义,如果该流程定义已有流程实例启动则删除时出错
repositoryService.deleteDeployment(deploymentId);
//设置true 级联删除流程定义,即使该流程有流程实例启动也可以删除,设置为false非级别删除方式,如果流程
//repositoryService.deleteDeployment(deploymentId,true);
}
- 如果该流程定义下没有正在运行的流程,则可以用普通删除。
- 如果该流程定义下存在已经运行的流程,使用普通删除报错,可用级联删除方法将流程及相关记录全部删除。
- 项目开发中级联删除操作一般只开放给超级管理员使用。
流程设计器持久化
流程设计默认是通过 H2
来完成数据的存储。而 H2 是基于内存来存储的。所以重启服务后数据丢失了。这时我们可以设置流程设计器的存储方式为MySQL。这样就能持久化的实现存储了。
调整数据库的连接信息,记得先要创建对应的数据库。
#datasource.driver=org.h2.Driver
#datasource.url=jdbc:h2:mem:activiti;DB_CLOSE_DELAY=-1
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://127.0.0.1:3306/activiti6ui?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
datasource.username=root
datasource.password=123456
#hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.dialect=org.hibernate.dialect.MySQLDialect
切换了数据的存储方案后,我们需要把对应数据库的驱动拷贝进来。
注意:MySQL启动不要高于8.0.19
版的驱动包,不然会出现LocalDateTime转换的问题。
以下就是产生的表信息。
然后我们就可以重新启动进行测试了。在act_de_model
表中就会保存我们创建的信息。
流程设计器汉化
- 页面的汉化
{
"GENERAL": {
"MAIN-TITLE": "Activiti",
"ERROR": {
"GENERIC": "抱歉,发生一个错误",
"UNKNOWN": "抱歉,执行请求操作时出错。",
"BAD_REQUEST": "执行请求的操作时出错。",
"NOT_FOUND": "您试图访问的资源不存在。",
"UNAUTHORIZED": "您应该登录才能执行请求的操作。",
"FORBIDDEN": "不允许您执行请求的操作。",
"INTERNAL_SERVER_ERROR": "抱歉,执行请求操作时发生意外错误。",
"QUOTA-EXCEEDED-RUNTIME-APPS": "作为试用用户,您只能同时部署 {{quota}} 应用程序。",
"QUOTA-EXCEEDED-LICENSE-APPS": " 许可证只允许同时部署{{quota}} 应用程序。"
},
"ACTION": {
"LOGOUT": "退出",
"HELP": "入门",
"EDIT-PROFILE": "编辑配置文件",
"SAVE": "保存",
"CANCEL": "取消",
"CLOSE": "关闭",
"DEPLOY": "部署",
"ABOUT": "关于 Alfresco Activiti"
}
},
"LOGIN": {
"TITLE": "登录",
"USERNAME": "用户名",
"USERNAME-PLACEHOLDER": "输入您的用户名",
"PASSWORD": "密码",
"PASSWORD-PLACEHOLDER": "输入您的密码",
"INVALID-CREDENTIALS": "域相关参数设置有误",
"ACTION": {
"CONFIRM": "登录"
}
},
"ACCOUNT": {
"ACTIVATE": {
"TITLE": "激活账户",
"ACTIVATING-MESSAGE": "请稍候 {{userFullName}} 我们正在激活您的账户...",
"SUCCESS-MESSAGE": "您的账户已激活。请在下面登录以开始设计和运行流程。",
"FAILURE-MESSAGE": "您的帐户无法激活。它可能已被激活,或者激活链接已过期。"
},
"RESET-PASSWORD-REQUEST": {
"MESSAGE": "忘记密码?在下面输入您的电子邮件地址以接收重置密码的电子邮件。",
"TITLE": "重置密码",
"EMAIL": "电子邮件地址",
"EMAIL-PLACEHOLDER": "输入您的电子邮件",
"SECURITY-SECTION": "安全检查",
"CONFIRM": "请求密码重置",
"SUCCESS-MESSAGE": "您很快就会收到一封邮件,其中包含重置密码的链接。",
"ERROR": {
"UNEXISTING-USER": "具有给定电子邮件地址的用户不存在。"
}
},
"RESET-PASSWORD": {
"TITLE": "重置密码",
"PASSWORD": "密码",
"PASSWORD-CONFIRM": "确认密码",
"PASSWORD-PLACEHOLDER": "输入新密码",
"PASSWORD-CONFIRM-PLACEHOLDER": "确认新密码",
"CONFIRM": "更改密码",
"LOADING": "正在重置密码...",
"SUCCESS-MESSAGE": "您的密码已更改。",
"LOGIN": "马上登录",
"FAILURE-MESSAGE": "您的密码无法重置。重置链接无效或已过期。"
}
},
"APP": {
"KICKSTART": {
"TITLE": "启动程序",
"DESCRIPTION": "创建流程模型、表单和应用程序定义,然后与其他人共享您的模型和定义。"
},
"TASKS": {
"TITLE": "任务应用程序",
"DESCRIPTION": "访问您的完整任务列表,并从任务流程应用程序处理分配给您的任何任务。同时,启动新的流程和任务。"
},
"IDENTITY-MANAGEMENT": {
"TITLE": "身份管理",
"TITLE-TENANT-ADMIN": "身份管理",
"DESCRIPTION": "管理您的配置文件:更改图片、名称和其他设置。作为管理员用户,管理用户和组。",
"DESCRIPTION-TENANT-ADMIN": "管理组织中的用户和组。"
},
"CUSTOM-APP" : {
"TITLE-TASKS": "任务",
"TITLE-PROCESSES": "流程"
},
"POPUP" : {
"ADD-APP-TITLE": "将APP添加到登录页",
"ADD-APP-SUMMARY": "将APP添加到登录页面"
},
"ACTION": {
"DELETE": "删除App"
},
"MESSAGE": {
"DELETED": "已成功删除APP"
}
}
}
- 编辑器汉化
如果有收获! 希望老铁们来个三连,点赞、收藏、转发。
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客