Version:0.9 StartHTML:0000000105 EndHTML:0000244551 StartFragment:0000000141 EndFragment:0000244511
Activiti
⼀、⼯作流
1
、⼯作流介绍
⼯作流
(Workflow)
,就是通过计算机对业务流程⾃动化执⾏管理。它主要解决的是
“
使在多个参与者 之间
按照
某种预定义的规则⾃动进⾏传递⽂档、信息或任务的过程
从⽽实现某个预期的业务⽬标, 或者促使此⽬标的实
现
”
。
2
、⼯作流的实现⽅式
在没有专⻔的⼯作流引擎之前,我们之前为了实现流程控制,通常的做法就是
采⽤状态字段的值来 跟踪流程
的变化情况。
这样不⽤⻆⾊的⽤户,通过状态字段的取值来决定记录是否显示。
针对有权限可以查看的记录,当前⽤户根据⾃⼰的⻆⾊来决定审批是否合格的操作。如果合格将状 态字段设置
⼀个值,来代表合格;当然如果不合格也需要设置⼀个值来代表不合格的情况。
这是⼀种最为原始的⽅式。通过状态字段虽然做到了流程控制,但是
当我们的流程发⽣变更的时候, 这种⽅式
所编写的代码也要进⾏调整。
那么有没有专业的⽅式来实现⼯作流的管理呢?并且可以做到业务流程变化之后,我们的程序可以 不⽤改变,
如果可以实现这样的效果,那么我们的业务系统的适应能⼒就得到了极⼤提升。
3
、⼯作流的实现原理分析
使⽤⼯作流的⽅式实现流程管理优势在于
与状态字段⽆关
,它始终都是从业务流程图中不断读取下⼀个节点,
当业务更新时,只需要更新流程图,
程序代码⽆需改动
。节点定义是需要规范的,
BPMN
就是这⼀套规范,⽽
activiti
作为⼀个⼯作流的软件也实现了这⼀套规范。
例如从图
3.1
更改为图
3.2
。
图
3.1
图
3.2
⼆、
Activiti
介绍
Activiti
是⼀个⼯作流引擎,
activiti
可以将业务系统中复杂的业务流程抽取出来,使⽤专⻔的建模语⾔
(
BPMN2.0
)进⾏定义,业务系统按照预先定义的流程进⾏执⾏,实现了业务系统的业务 流程由
activiti
进⾏管
理,减少业务系统由于流程变更进⾏系统升级改造的⼯作量,从⽽提⾼系统的健壮性,同时也减少了系统开发维护
成本。官⽅⽹站:
https://www.activiti.org/
,官⽅⽂档:
https://www.activiti.org/userguide/#
1
、
BPM
BPM
(
Business Process Management
),即业务流程管理,是⼀种以规范化的构造端到端的卓越业务流程
为中⼼,以持续的提⾼组织业务绩效为⽬的系统化⽅法,常⻅商业管理教育如
EMBA
、
MBA
等均将
BPM
包含在
内。
2
、
BPM
软件
BPM
软件就是根据企业中业务环境的变化,推进⼈与⼈之间、⼈与系统之间以及系统与系统之间的整合及调
整的经营⽅法与解决⽅案的
IT
⼯具。 通常以
Internet
⽅式实现信息传递、数据同步、业务监控和企业业务流程的
持续升级优化,从⽽实现跨应⽤、跨部⻔、跨合作伙伴与客户的企业运作。通过
BPM
软件对企业内部及外部的业
务流程的整个⽣命周期进⾏建模、⾃动化、管理监控和优化,使企业成本降低,利润得以⼤幅提升。
BPM
软件在企业中应⽤领域⼴泛,凡是有业务流程的地⽅都可以
BPM
软件进⾏管理,⽐如
企业⼈事办公管
理、采购流程管理、公⽂审批流程管理、财务管理等。
3
、
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
的最终版本。
BPMN
是⽬前被各
BPM
⼚商⼴泛接受的
BPM
标准。
Activiti
就是使⽤
BPMN 2.0
进⾏流程建模、流程执⾏管
理
,它包括很多的建模符号,⽐如:
Event
⽤⼀个圆圈表示,它是流程中运⾏过程中发⽣的事情,
Bpmn
图形其实
是通过
xml
表示业务流程。
三、如何使⽤
Activiti
三、如何使⽤
Activiti
1
、引⼊依赖
<dependency>
<groupId>
org.activiti
</groupId>
<artifactId>
activiti-engine
</artifactId>
<version>
6.0.0
</version>
</dependency>
<dependency>
<groupId>
org.activiti
</groupId>
<artifactId>
activiti-spring-boot-starter-basic
</artifactId>
<version>
6.0.0
</version>
</dependency>
需在启动类上加上
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
;因为
activiti-spring-boot-starter-basic
中引⽤了
spring-boot-starter-security
2
、添加配置
#
校验流程⽂件,默认校验
resources
下的
processes
⽂件夹⾥的流程⽂件,默认
true
spring.activiti.check-process-definitions
=
false
#activiti
在流程引擎启动就激活
AsyncExecutor,
异步,默认
true
spring.activiti.async-executor-activate
=
false
#
建表规则,默认
false
#flase
: 默认值。
activiti
在启动时,会对⽐数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。
#true
:
activiti
会对数据库中所有表进⾏更新操作。如果表不存在,则⾃动创建。
#create_drop
: 在
activiti
启动时创建表,在关闭时删除表(必须⼿动关闭引擎,才能删除表)。
#drop-create
: 在
activiti
启动时删除原来的旧表,然后在创建新表(不需要⼿动关闭引擎)
spring.activiti.database-schema-update
=
true
#
流程⽂件路径,默认
classpath:/processes/
spring.activiti.process-definition-location-prefix
=
classpath
:
/processes/
#
记录历史等级 可配置的历史级别有
none, acitivity, audit, all;
默认
audit
spring.activiti.history-level
=
audit
完成上述两步操作,数据库会⾃动⽣成
activiti
的表结构。
3
、安装流程设计器
1
、官⽹搜索
actiBPM
插件
https://plugins.jetbrains.com/
2
、了解流程设计器的使⽤
3
、仅⽀持
IDEA2019
,不⽀持
IDEA2020
以上版本
属性名称 属性说明
avtiviti:formKey Activiti
扩展的
formKey
属性,可以⽤来指定启动事件关联的表单⽂件
activiti:initiator activiti
扩展的
initiator
事件,可以⽤来记录启动流程⼈的
ID
,启动流程之后此属性指定的
变量就会⾃动设置当前⼈的名称
4
、了解核⼼
API
的使⽤
四、流程设计器
1
、
idea
插件,官⽹搜索
actiBPM
插件
https://plugins.jetbrains.com/
A
:启动事件
1.
空启动事件
以上
XML
表示⼀个空启动事件,由于
startEvent
标签内没有任何元素定义,因此表示⼀个空启动事件
<startEvent
id
=
"startevent"
name
=
"
开始
"
></startEvent>
属性名称 属性说明
timeDate
⼀次性定时启动,具体到⼀个⽇期
timeDuration
设置多⻓时间之后启动流程
timeCycle
周期性启动任务,⽤来设定循环的时间间隔,表示多⻓时间执⾏⼀次循环
2.
定时启动事件
定时启动事件可以⽤于⼀次性定时启动,也可以⽤于特定时间定时启动
以上
XML
就表示⼀个空定时启动事件
3.
异常启动事件
异常启动事件可以触发⼀个异常⼦流程,但不能通过
API
⽅式启动,总是在另外⼀个⼦流程抛出异常结束事件的时
候,被触发
异常启动事件
"
捕获型
"
,⽽异常结束事件是抛出型的。
4.
消息启动事件
消息启动事件可以通过⼀个消息名称触发,从⽽启动⼀个流程实例,还可以结合消息抛出事件⼀起使⽤。
B
:结束事件
1.
空结束事件
结束事件是抛出型的。空结束事件不处理抛出结果,空结束事件⼀般⽤于正常结束流程。
2.
异常结束事件
异常结束事件时有抛出结果的,它定义了需要抛出的错误代码,如果找到了异常开始事件定义的异常代码,则会触
发异常开始事件,否则按照空结束事件处理。
3.
终⽌结束事件
他可以终⽌⼀个流程实例的执⾏
4.
取消结束事件
取消结束事件可以取消⼀个事务⼦流程的执⾏,同时也能在⼦流程中使⽤,当⼦流程在执⾏过程中出现异常时,可
以设置⼀个取消结束事件。
<startEvent
id
=
"timerstartevent1"
name
=
"Timer start"
>
<timerEventDefinition></timerEventDefinition>
</startEvent>
C
:⽹关
1
、排它⽹关
内部是⼀个
“X”
图标,排他⽹关(也叫异或(
XOR
)⽹关,或叫基于数据的排他⽹关),⽤来在流程中实现决策。
当流程执⾏到这个⽹关,所有分⽀都会判断条件是否为
true
,如果为
true
则执⾏该分⽀,如果都为
false
,则抛出
异常。
注意,排他⽹关只会选择⼀个为
true
的分⽀执⾏
。
(
即使有两个分⽀条件都为
true
,排他⽹关也会只选择
XML
中的第⼀个顺序流(也只有这⼀条)去执⾏
)
2
、并⾏⽹关
内部是⼀个
“
加号
”
图标。并⾏⽹关⽤来对并发的任务进⾏流程建模,并⾏⽹关的任务取决于输⼊,输出顺序流。
并⾏⽹关不判断条件。如果在与并⾏⽹关连接的序列流上定义了条件,则它们被简单地忽略。
拆分:并⾏执⾏所有的输出输⼊顺序流,并且为每⼀条顺序流创建⼀个并⾏执⾏线路
汇聚:所有从并⾏⽹关拆分并执⾏完成的线路均在此等候,直到所有的线路都执⾏完成才继续向下执⾏
3
、包含⽹关
内部包含⼀个圆圈图标,可以看做是排他⽹关和并⾏⽹关的结合体。 和排他⽹关⼀样,你可以在
外出顺序流上定
义条件
,包含⽹关会解析它们。 但是主要的区别是
包含⽹关可以选择多于⼀条顺序流
,这和并⾏⽹关⼀样。
分⽀:所有外出顺序流的条件都会被解析,结果为
true
的顺序会以并⾏⽅式继续执⾏,会为每个顺序流创建⼀个分
⽀;
汇聚:所有并⾏分⽀达到包含⽹关,会进⼊等待状态,直到每个进⼊顺序流的分⽀都到达;这是与并⾏⽹关的最⼤
不同;换句话说,包含⽹关只会等待进⼊顺序流的分⽀;在汇聚之后,流程会穿过包含⽹关继续执⾏;
4
、基于事件⽹关
事件⽹关是专⻔为中间捕获事件设置的,它允许多个输出流指向多个不同的中间捕获事件。当流程执⾏到事件⽹
关后流程处于等待的状态,因为中间等待事件需要依赖中间抛出事件触发。
D
:任务
1
、⽤户任务
⽤户任务⽤来设置必须由⼈员完成的⼯作。 当流程执⾏到⽤户任务,会创建⼀个新任务, 并把这个新任务加⼊到
分配⼈或群组的任务列表中。
属性名称 属性说明
activiti:assignee
⽤来指定⽤户任务的处理⼈
activiti:cadidateUsers
⽤来指定⽤户任务的候选⼈,多个⽤逗号隔开
activiti:cadidateGroups
⽤来指定多个候选组,多个⽤逗号隔开
activiti:dueDate
设置任务的到期⽇,通常⽤变量代替⽽不是设定⼀个具体的⽇期
activiti:priority
设定任务的优先级,取值区间
[0,100]
以上
XML
定义了⼀个⽤户任务
2
、脚本任务
脚本任务可以运⾏引擎依赖的语⾔之外的脚本语⾔。
3
、
Java
服务任务
⽤来调⽤外部
java
类。
4
、
Web Service
任务:
⽤来同步调⽤⼀个外部的
Web service
5
、邮件任务
邮件任务可以通过
Activiti
发送邮件,其中邮件的信息通过变量的⽅式传递
6
、
Java
接收任务
接收任务是⼀个简单任务,它会等待对应消息的到达。
7
、业务规则任务
功能和
ServiceTask
⼀样
E
:⼦流程
1
、⼦流程
⼀个包含其他节点,⽹关,事件等等的节点。 它⾃⼰就是⼀个流程,同时是更⼤流程的⼀部分。
五、
7
⼤核⼼接⼝、
28
张表
<process
id
=
"myProcess"
name
=
"My process"
isExecutable
=
"true"
>
<userTask
id
=
"usertask1"
name
=
"User Task"
></userTask>
</process>
表分类 表名 解释
⼀般数据
ACT_GE_BYTEARRAY
通⽤的流程定义和流程资源
ACT_GE_PROPERTY
系统相关属性
流程历史记录
ACT_HI_ACTINST
节点活动历史表(对应流程的所有节点的活动历史)
ACT_HI_ATTACHMENT
历史的流程附件
ACT_HI_COMMENT
历史的说明性信息
ACT_HI_DETAIL
历史的流程运⾏中的细节信息
ACT_HI_IDENTITYLINK
历史的流程运⾏过程中⽤户关系
ACT_HI_PROCINST
历史的流程实例
五、
7
⼤核⼼接⼝、
28
张表
RepositoryService
:提供⼀系列管理流程部署和流程定义的
API
。
RuntimeService
:在流程运⾏时对流程实例进⾏管理与控制。
TaskService
:对流程任务进⾏管理,例如任务提醒、任务完成和创建任务等。
IdentityService
:提供对流程⻆⾊数据进⾏管理的
API
,这些⻆⾊数据包括⽤户组、⽤户及它们之间的关系。
ManagementService
:提供对流程引擎进⾏管理和维护的服务。
HistoryService
:对流程的历史数据进⾏操作,包括查询、删除这些历史数据。
FormService
:表单服务。
表结构
1. act_ge_
通⽤数据表,
ge
是
general
的缩写,⽤于各种⽤例
2. act_hi_
历史数据表,
hi
是
history
的缩写,对应
HistoryService
接⼝,这些表包含历史数据,如过去的流程实
例、变量、任务等。
Activit
默认提供了
4
种历史级别,可在配置⽂件中配置:
Ø
none
:
不保存任何历史记录,可以提⾼系统性能;
Ø
activity
:保存所有的流程实例、任务、活动信息;
Ø
audit
:也是
Activiti
的
默认
级别,保存所有的流程实例、任务、活动、表单属性;
Ø
full
:最完整的历史记录,除了包含
audit
级别的信息之外还能保存详细,例如:流程变量。
对于⼏种级别根据对功能的要求选择,如果需要⽇后跟踪详细可以开启
full
。
3. act_id_
身份数据表,
id
是
identity
的缩写,对应
IdentityService
接⼝,这些表包含标识信息,如⽤户、组等;
如果
Activiti
被集成在某⼀系统当中的话,这些表可以不⽤,可以直接使⽤现有系统中的⽤户或组信息。
4. act_re_
流程存储表,
re
是
repository
的缩写,对应
RepositoryService
接⼝,这些表中保存⼀些
‘
静态
’
信息,如
流程定义和流程资源(如图⽚、规则等)。
5. act_ru_
运⾏时数据表,
ru
是
runtime
的缩写,对应
RuntimeService
接⼝和
TaskService
接⼝,这些运⾏时表包
含流程实例、⽤户任务、变量、作业等的运⾏时数据。
Activiti
只保存流程实例在执⾏过程中的运⾏时数据,
并且当流程结束后会⽴即移除这些数据,
这是为了保证运⾏时表尽量的⼩并运⾏的⾜够快;
ACT_HI_TASKINST
历史的任务实例
ACT_HI_VARINST
历史的流程运⾏中的变量信息
⽤户⽤户组表
ACT_ID_GROUP
身份信息
-
组信息
ACT_ID_INFO
身份信息
-
⽤户扩展信息
ACT_ID_MEMBERSHIP
身份信息
-
⽤户和组关系的中间表
ACT_ID_USER
身份信息
-
⽤户信息
流程定义表
ACT_RE_DEPLOYMENT
部署单元信息
ACT_RE_MODEL
模型信息
ACT_RE_PROCDEF
已部署的流程定义
运⾏实例表
ACT_RU_EVENT_SUBSCR
运⾏时事件
ACT_RU_EXECUTION
运⾏时流程执⾏实例
ACT_RU_IDENTITYLINK
运⾏时⽤户关系信息
ACT_RU_JOB
运⾏时作业
ACT_RU_TASK
运⾏时任务
ACT_RU_VARIABLE
运⾏时变量表
ACT_RU_DEADLETTER_JOB
运⾏时死信
ACT_RU_TIMER_JOB
运⾏时定时作业
ACT_RU_SUSPENDED_JOB
运⾏时暂停作业
其他
ACT_EVT_LOG
事件⽇志
ACT_PROCDEF_INFO
流程定义信息
六、
Activiti API
1
、部署流程定义
1
、与
静态
数据(例如流程定义)相关的所有内容都通过
RepositoryService
访问。从概念上讲,每个这样的静态
数据都是
Activiti
引擎
存储库
的内容。
2
、为了让
Activiti
引擎知道这个过程,我们必须先
部署
它。部署意味着引擎会将
BPMN 2.0 xml
解析为可执⾏⽂
件,并且将为
部署中
包含的每个流程定义添加新的数据库记录。这样,当引擎重新启动时,它仍然会知道所有已
部
署的
进程
//
通过⽂件路径部署流程定义
Deployment deployment
=
repositoryService
.
createDeployment
().
addClasspathResource
(
"processes/"
+
fileName
).
deploy
();
//
获得流程定义
ProcessDefinition processDefinition
=
repositoryService
.
createProcessDefinitionQuery
().
deploymentId
(
deployment
.
getId
()).
singl
eResult
();
String
processKey
=
processDefinition
.
getKey
();
String
processDefinitionId
=
processDefinition
.
getId
();
//
获取
BPMN
模型
BpmnModel model
=
repositoryService
.
getBpmnModel
(
processDefinitionId
);
//
获取流元素
Collection
<
FlowElement
>
flowElements
=
model
.
getMainProcess
().
getFlowElements
();
int
i
=
1
;
for
(
FlowElement e
:
flowElements
) {
//
⽤户任务元素
if
(
e
instanceof
UserTask
) {
UserTask userTask
=
(
UserTask
)
e
;
//
流程候选⼈配置项
CandidateDefPO candidateDefPO
=
new
CandidateDefPO
();
candidateDefPO
.
setTaskDefName
(
userTask
.
getName
());
candidateDefPO
.
setApplyType
(
processKey
);
candidateDefPO
.
setTaskDefId
(
userTask
.
getId
());
candidateDefPO
.
setSortNo
(
i
++
);
candidateDefService
.
add
(
candidateDefPO
);
}
}
由于需要灵活配置流程审核⼈,并使⽤系统的账号体系,
activiti
⾃带的表结构不适⽤。故解析
BpmnModel
中的
UserTask
,将审核节点信息存储到⾃定义的业务表。
CREATE TABLE
`cs_candidate_def`
(
`id`
bigint
(
20
)
NOT
NULL
AUTO_INCREMENT
,
`apply_type`
varchar
(
32
)
DEFAULT
NULL
COMMENT
'
申请类型(报修关闭申请:
repairCloseApply
;
投诉申请关闭:
complaintCloseApply
;公告审核:
announceApply
;物业报修:
repairApply
;投诉建议:
complainApply
;⻋位审核:
parkingSpaceRentAudit
;调度台:
dispatch
;住户审核:
household
)
'
,
`task_def_id`
varchar
(
50
)
NOT
NULL
COMMENT
'
任务定义
ID'
,
`task_def_name`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'
任务名
'
,
`org_id_position_id`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'
部⻔
ID:
岗位
(
多个逗号隔开
,
⽆部⻔则
为同级
)
(暂⽆此功能)
'
,
`org_name_position_name`
varchar
(
1000
)
DEFAULT
NULL
COMMENT
'
部⻔名
:
岗位
(
多个逗号隔开
,
⽆部
⻔则为同级
)
(暂⽆此功能)
'
,
`real_name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'
处理⼈真实名称(多个逗号隔开)
'
,
`account_id`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'
处理⼈
ID(
多个逗号隔开
)'
,
`role_id`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'
处理⼈⻆⾊
Id(
多个逗号隔开
)'
,
`role_name`
varchar
(
255
)
DEFAULT
NULL
COMMENT
'
处理⼈⻆⾊名称
(
多个逗号隔开
)'
,
`is_end`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'
是否结束
'
,
`sort_no`
tinyint
(
1
)
DEFAULT
NULL
COMMENT
'
排序
'
,
`create_by`
bigint
(
20
)
DEFAULT
NULL
COMMENT
'
创建者账号
ID'
,
`create_by_name`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'
创建者姓名
'
,
`create_time`
datetime
DEFAULT
NULL
COMMENT
'
创建时间
'
,
`update_by`
varchar
(
50
)
DEFAULT
NULL
COMMENT
'
更新⼈
'
,
`update_time`
datetime
DEFAULT
NULL
COMMENT
'
更新时间
'
,
`is_deleted`
tinyint
(
1
)
DEFAULT
'0'
COMMENT
'
删除状态
0
:未删除
1
:删除
'
,
PRIMARY KEY
(
`id`
)
USING BTREE
)
ENGINE
=
InnoDB AUTO_INCREMENT
=
27
DEFAULT
CHARSET
=
utf8
COMMENT
=
'
流程定义基础表
'
;
2
、配置流程候选⼈
1
、虽然
Activiti
提供了⼀个身份管理组件,该组件通过
IdentityService
公开,但不检查提供的⽤户是否被身份组件
知道。这允许
Activiti
在嵌⼊到应⽤程序中时与现有的身份管理解决⽅案集成。
查询流程定义信息,并配置审核⼈。
//
查询流程定义信息
ProcessDefinitionQuery pq
=
repositoryService
.
createProcessDefinitionQuery
().
latestVersion
();
List
<
ProcessDefinition
>
processDefinitionList
=
pq
.
orderByProcessDefinitionVersion
().
asc
().
list
();
3
、启动流程
1
、将流程定义部署到
Activiti
引擎后,我们可以从中启动新的流程实例。对于每个流程定义,通常有许多流程实
例。流程定义是
蓝图
,⽽流程实例是它的运⾏时执⾏。
2
、流程实例启动时提供了⼀些流程变量,因为第⼀个⽤户任务的描述将在其表达式中使⽤这些变量。通常使⽤流
程变量是因为它们为特定流程定义的流程实例赋予意义。通常,流程变量使流程实例彼此不同。
//
启动流程
Map
<
String
,
Object
>
variables
=
dto
.
toMap
();
runtimeService
.
startProcessInstanceByKey
(
processKey
,
dto
.
getApplyNo
(),
variables
);
//
查询流程实例的当前任务
Task task
=
taskService
.
createTaskQuery
().
processInstanceBusinessKey
(
dto
.
getApplyNo
())
.
singleResult
();
//
为任务添加候选⼈
taskService
.
addCandidateUser
(
task
.
getId
(),
candidate
);
//
为任务添加候选⼈组
taskService
.
addCandidateGroup
(
task
.
getId
(),
candidate
);
}
4
、查询待处理任务列表
//
获取任务查询实例
TaskQuery tq
=
taskService
.
createTaskQuery
();
//
声明任务的候选⼈
tq
.
taskCandidateUser
(
proTaskQueryDTO
.
getCandidateAccountId
());
//
声明流程定义
key
tq
=
tq
.
processDefinitionKeyIn
(
"repair"
);
//
声明过滤条件
Map
<
String
,
Object
>
queryMap
=
new
HashMap
<>
(
1
);
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
queryMap
.
entrySet
()) {
if
(
entry
.
getValue
()
!=
null
&& !
""
.
equals
(
entry
.
getValue
().
toString
())) {
tq
=
tq
.
processVariableValueLike
(
entry
.
getKey
(),
"%"
+
entry
.
getValue
().
toString
()
+
"%"
);
}
}
//
获取任务列表
List
<
Task
>
taskList
=
tq
.
orderByTaskDescription
().
desc
().
listPage
(
pageDTO
.
getStartIndex
(),
pageDTO
.
getPageSize
());
;
//
查询任务参数
for
(
Task task
:
taskList
) {
Map
<
String
,
Object
>
map
=
taskService
.
getVariables
(
task
.
getId
());
list
.
add
(
map
);
}
5
、完成任务
//
查询任务
Task task
=
taskService
.
createTaskQuery
().
taskId
(
"id"
).
singleResult
();
//
流程变量
Map
<
String
,
Object
>
taskVariables
=
new
HashMap
<
String
,
Object
>
();
//${deal_type==1}
//
如果参数在流程图中作为表达式,则⽤于判断流程图顺序流⾛向;
taskVariables
.
put
(
"deal_type"
,
"1"
);
//
普通流程变量,存到历史表供后续查询。
taskVariables
.
put
(
"remark"
,
"We have a tight deadline!"
);
taskService
.
complete
(
task
.
getId
(),
taskVariables
);
//
完成任务
taskService
.
complete
(
task
.
getId
(),
variables
);
6
、查询已完成任务列表
//
创建历史任务实例查询器
HistoricTaskInstanceQuery tq
=
historyService
.
createHistoricTaskInstanceQuery
();
//
设置任务执⾏⼈
tq
.
taskAssignee
(
proTaskQueryDTO
.
getCandidateAccountId
());
if
(
StringUtils
.
isNotEmpty
(
proTaskQueryDTO
.
getApplyType
())) {
//
申请类型(多个英⽂逗号隔开)
tq
=
tq
.
processDefinitionKeyIn
(
Arrays
.
asList
(
proTaskQueryDTO
.
getApplyType
().
split
(
","
)));
}
//
获取查询结果
List
<
HistoricTaskInstance
>
taskList
=
tq
.
orderByHistoricTaskInstanceEndTime
().
desc
().
listPage
(
0
,
proTaskQueryDTO
.
getCount
());
List
<
ProcessInstDTO
>
processInstDTOList
=
new
ArrayList
<>
();
ProcessInstDTO processInstDTO
;
Map
<
String
,
Object
>
map
;
//
处理查询结果
for
(
HistoricTaskInstance task
:
taskList
) {
//
获取该任务的流程变量
List
<
HistoricVariableInstance
>
historicVariableInstanceList
=
historyService
.
createHistoricVariableInstanceQuery
().
processInstanceId
(
task
.
getProcessI
nstanceId
()).
list
();
map
=
new
HashMap
<>
();
for
(
HistoricVariableInstance variableInstance
:
historicVariableInstanceList
)
{
map
.
put
(
variableInstance
.
getVariableName
(),
variableInstance
.
getValue
());
}
processInstDTO
=
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
map
),
ProcessInstDTO
.
class
);
processInstDTOList
.
add
(
processInstDTO
);
}
return
processInstDTOList
;
}
7
、删除流程定义
/**
*
删除流程定义
*
* @param deployId
部署流程
ID
* @param cascade
是否级联删除流程实例、历史流程实例和作业。
*/
@Override
public
void
deleteDeploy
(
String
deployId
,
boolean
cascade
) {
repositoryService
.
deleteDeployment
(
deployId
,
cascade
);
}
8
、暂停和激活流程定义
1
、可以暂停流程定义。当流程定义被挂起时,⽆法创建新的流程实例(会抛出异常)。
暂停流程定义是通过以下⽅式完成的
RepositoryService
:
//
暂停流程定义
repositoryService
.
suspendProcessDefinitionByKey
(
"repair"
);
try
{
runtimeService
.
startProcessInstanceByKey
(
"repair"
);
}
catch
(
ActivitiException e
) {
e
.
printStackTrace
();
}
//
激活流程定义
repositoryService
.
activateProcessDefinitionByKey
(
"repair"
);
9
、⾃定义查询
1
、有时您需要更强⼤的查询,例如使⽤
OR
运算符的查询或使⽤查询
API
⽆法表达的限制。对于这些情况,我们
引⼊了原⽣查询,它允许您编写⾃⼰的
SQL
查询。返回类型由您使⽤的
Query
对象定义,并且数据被映射到正确
的对象中,例如
Task
、
ProcessInstance
、
Execution
等
......
。
List
<
Task
>
tasks
=
taskService
.
createNativeTaskQuery
()
.
sql
(
"SELECT count(*) FROM "
+
managementService
.
getTableName
(
Task
.
class
)
+
" T WHERE
T.NAME_ = #{taskName}"
)
.
parameter
(
"taskName"
,
"gonzoTask"
)
.
list
();
long
count
=
taskService
.
createNativeTaskQuery
()
.
sql
(
"SELECT count(*) FROM "
+
managementService
.
getTableName
(
Task
.
class
)
+
" T1, "
+
managementService
.
getTableName
(
VariableInstanceEntity
.
class
)
+
" V1 WHERE
V1.TASK_ID_ = T1.ID_"
)
.
count
();
10
、变量
1
、每个流程实例都需要并使⽤数据来执⾏它存在的步骤。在
Activiti
中,这些数据称为
变量
,它们存储在数据库
中。变量可⽤于表达式(例如在独占⽹关中选择正确的传出序列流)、调⽤外部服务时的
java
服务任务(例如提
供输⼊或存储服务调⽤的结果)等。
2
、任何
startProcessInstanceXXX
⽅法都有⼀个可选参数,⽤于在创建和启动流程实例时提供变量。例如,来⾃
RuntimeService
:
ProcessInstance
startProcessInstanceByKey
(
String
processDefinitionKey
,
Map
<
String
,
Object
>
variables
);
3
、可以在流程执⾏期间添加变量。例如(
RuntimeService
):
void
setVariable
(
String
executionId
,
String
variableName
,
Object
value
);
void
setVariableLocal
(
String
executionId
,
String
variableName
,
Object
value
);
void
setVariables
(
String
executionId
,
Map
<
String
,
?
extends
Object
>
variables
);
void
setVariablesLocal
(
String
executionId
,
Map
<
String
,
?
extends
Object
>
variables
);
可以为给定的
execution
设置
local
变量。该变量仅在该
execution
中可⻅,在执⾏树中不可⻅。如果数据不应该传
播到流程实例级别,或者该变量对于流程实例中的某个路径具有新值(例如,当使⽤并⾏路径时),这会很有⽤。
11
、表达式
1
、
Activiti
使⽤
UEL
进⾏表达式解析。
表达式可⽤于
Java
服务任务
、
执⾏侦听器
、
任务侦听器
和
条件序列流
。
1.1
、
值表达式
:解析为⼀个值
${myVar}
${myBean.myProperty}
1.2
、
⽅法表达式
:调⽤⼀个⽅法,带或不带参数。
${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}
七、
Activiti
优势总结
1
、使⽤⼯作流的⽅式实现流程管理优势在于
与状态字段⽆关
,它始终都是从业务流程图中不断读取下⼀个节点,
当业务更新时,只需要更新流程图,
程序代码⽆需改动
。
2
、快速查询各种业务的待处理任务,⽆需到各个业务表查询。
3
、
Activiti
原⽣⽀持
Spring
,这⼀点对企业应⽤来说尤为重要:可以很轻松地进⾏
Spring
集成,⾮常⽅便管理事务
和解析表达式
( Expression)
。
4
、分离运⾏时与历史数据,表结构设计⽅⾯也遵循运⾏时与历史数据的分离,这样的设计可以快速读取运⾏时数
据,仅当需要查询历史数据时再从专⻔的历史数据表中读取。这种设计⽅式可以⼤幅提⾼数据的存取效率,尤其是
当数据⽇积⽉累时依然能够快速反应。
5
、利⽤流程设计器设计
BPMN 2.0
规范的流程图