文档章节

《Activiti实战》摘抄&笔记2

v1-alpha
 v1-alpha
发布于 2016/07/05 22:57
字数 5770
阅读 651
收藏 2

##用户与组及部署管理
用户和工作流 作为 工作流引擎的基础数据(基础组件),有必要先了解学会如何管理及其之间的关系,有助于接下来的学习和理解。
1)用户、组的关系(数据模型),及其管理——CURD的API;
2)流程定义的管理CURD,包括部署、删除、读取部署的资源文件;

###用户与组 IdentifyService是用来管理user和group的

用户 :User 在各种需要人工参与的系统中,用户和组是一个身份系统(身份模块)的基础,在Activiti中用户和组主要是应用与用户任务。

:Group 在Activiti中,组的类型分2种:assignment和security-role,前者是一种普通的岗位角色,是用户分配业务中的功能权限,后者是安全角色,可以从全局管理用户组织及整个流程的状态。

用户与组的关系 : MemberShip

用户任务中的用户与组
当不确定要将一个任务分配给哪个人处理时,就需要把任务指定给多个候选人或候选组,谁签收了这个任务,谁就可以办理任务。
候选组:activiti:candidateGroups 候选人:activiti:candidateUsers

###部署流程资源 流程资源:在启动流程或流程实例运行过程中会被读取,一般包含:
1)流程定义文件: 扩展名为bpmn20.xml和bpmn;
2)流程定义的图片:用BPMN2.0规范的各种图形描绘,一般用PNG格式;
3)表单文件:把表单内容保存在一个文件中,扩展名为form;
4) 规则文件:例如Drools的规则文件,其扩展名为drl

部署流程资源都是通过RepositoryServce的createDeployment()方法在创建DeploymentBuilder对象后调用不同的方法部署资源,包括classpath, InputStream, 字符串, zip格式压缩包。 部署是指把流程定义文件持久化到数据库。

一次部署可以包含单个或多个资源文件,调用一次DeploymentBuilder的deploy()方法即可称之为一次部署;部署对象可以记录本次部署时间,并且本次部署的资源文件记录中会关联本次部署ID。

部署的执行过程:“开始部署”开始一次部署操作,然后保存本次所有的资源到字节流库中,紧接着处理(解析)本次部署的资源,流程引擎内置了2个处理器(解析流程定义、解析规则文件)用来解析常用的格式,部署完成后可能还有一些触发器需要执行。

一个流程定义会对应一个图片资源。图片可以由引擎自动生成,或者与流程定义一起部署(压缩包方式),这样引擎不再自动生成图片资源,而是使用部署包中的图片资源。

##任务表单 动态表单 :使用activiti:formProperty, 表单字段定义在流程定义文件中。动态表单的字段以键值的形式存储在变量表(ACT_HI_DETAIL)中。
HistoricFormProperty, HistoricVariableUpdate
自定义表单的字段类型:org.activiti.engine.impl.form.AbstractFormType,内置支持:boolean, date,double,enum,long,string

外置表单 :流程运行时表单内容(从部署的表单文件中读取)会原样显示在页面,并支持动态表单的字段值的自动填充功能。外置表单除了配置一个文件的相对路径外还可以配置URL
Activiti支持自定义表单引擎以适应各种场景,默认的表单引擎是基于Juel实现的,该引擎可以计算表单文件中EL表达式作为表单内容,所以当调用FormService接口的getRendered*Form()方法后得到的内容是经过Form引擎处理过的。

普通表单 :直接把表单的内容写在表现层(JSP、JSF、HTML等)文件中,一个用户任务对应一个页面(或者将内容官方在一个文件中,根据节点判断显示哪部分内容)。这样的做法适用于业务相对固定、业务比较复杂、流程相对固定但表现层变化比较多的情况。有涉及到统一事务管理

业务和流程数据库分离
业务表和流程建立双向关系是可选的,这样做的目的是在查询时可以明确知道业务对应的流程数据ID,假如没有在业务中保存流程实例ID,那么两者联合查询要以流程为入口,如此在性能方面就大打折扣。这样做还有另外一个母的,那就是可以区分业务数据的状态,例如有些系统中会区分已启动流程和未启动流程的数据,根据业务数据的“PROCESS_INSTANCE_ID"字段是否为空可以很容易地查询不同状态的数据

##Activiti与容器集成 ###流程引擎工厂 ProcessEngineFactoryBean生成ProcessEngine
1)configureExpressionManager:SpringExpressionManager
2)configureExternallyManagedTransactions:
3)processEngineConfiguration.setBeans :

SpringProcessEngineConfiguration在ProcessEngineConfigurationImpl基础上增加功能:
1)事物管理器的配置:transactionManager;
2)自动部署流程定义:Collection<AutoDeploymentStrategy> deploymentStrategies & Resource[] deploymentResources:通过spring创建的流程可以自动把定义的资源部署到引擎中。部署的方式是利用Spring提供的Resource功能实现的,可以使用多种方式配置资源路径。使用DeploymentBuilder.enableDeplicateFiltring()排除重复的流程定义,只有流程数据库中没有和自动部署的流程定义相同的记录才会部署,否则会忽略,不会出现启动多次应用后部署多个版本的流程定义问题。

###表达式 在流程定义中几乎所有的属性都可以使用变量方式定义,这样可以在运行中灵活地设置。在流程定义文件中出现的判断条件的语句或者调用一个Bean的方法都成为表达式。对表达式的解析由JUEL根据UEL规范实现,之后Activiti又对JUEL进行扩展满足更多地需求。
示例:

${myVar}  
${myVar.name}	
${serviceBean.confirm()} 
${serviceBean.confirm('xxxx')}
${serviceBean.confirm(name,execution)}

**引擎内置的三个变量
1)execution : 此变量在运行阶段总是可以调用,对应接口org.activiti.engine.delegate.DelegateExecution,从该接口的get方法中看出可以获取那些信息。
2)task: DelegateTask接口,仅支持用户任务,而且先顶为expression类型的表达式。
3)authenticatedUserId:此变量尽在启动流程实例前调用IdentityService的setAuthenticatedUserId()方法时才会由引擎提供,使用ThreadLocal保存

在Activiti中表达式应用非常广泛,通过表达式可以动态计算(读取)一切可以计算的表达式,从而获取动态值。例如可以动态设置用户任务的办理人(activiti:assignee属性),执行一个Java Service任务,或者执行Execution监听器、Task监听器、还有在请假流程中排他分支的输出流条件判断等。
在Activiti中,所有表达式中出现的变量均需要实现序列化接口java.io.Serializable。这样能保存到数据库里。对于3个内置变量,仅能通过表达式获取,不能通过RuntimeService或TaskService的getVariable()方法获取。

使用Spring管理变量
使用Spring管理变量可以避免由引擎保存复杂变量(自定义Bean)到数据库。就是processEngineConfiguration.setBeans

###监听器 1)流程实例级别的监听器均要实现接口org.activiti.engine.delegate.ExecutionListener,此接口仅有一个方法且传入一个DeletegaExecution对象作为参数;
2)任务级别的监听器与流程实例需要实现接口org.activiti.engine.delegate.TaskListner,都需要实现一个notify()方法,但参数是DelegateTask,而表达式注入字段的类型则必须是Expression。

##邮箱服务

##多实例 多实例允许多个用户协作完成一个任务,或者批量处理某项任务等。配置了多实例特性的活动在流程运行时依次(顺序方式)或单次批量(并行方式)创建活动实例,实例的数量由不同的参数决定。
会签: 就是主办人联合其他有关人员联合办理的过程,例如主办单位下发公文,一般需要多个部门共同审核通过之后才允许对外发布。再如员工离职需要各个部门签字、盖章确认之后方可离职,这一过程也称为会签。会签就是多实例的一个经典适用场景。

###非用户任务 非用户任务可以直接指定任务实例的数量(引擎内部会循环创建任务实例),也就是多实例任务执行的次数;用户任务如果也像非用户任务一样指定任务的数量就显得没有意义,因为用户任务没有任务的办理人。因此非用红任务创建多实例任务,可以通过配置多实例任务的nrOfInstances参数来实 现,当然该参数可以配置为固定值,也可以通过变量方式动态配置。

多实例的内置变量:nrOfInstances、nrOfActiviInstances、nrOfCompletedInstances、loopCounter,可以直接应用于表达式中,也可由在任务监听类中获取内置变量以便协助处理业务逻辑。

###用户任务多实例 和Java Service一样,如果用户任务也通过设置loopCardinality元素的值来决定实例数量,就显得毫无意义,因为缺少了用户任务的主要特性——人,所以用户任务实例数量就需要由参与的人数决定。

会签一般由主办人发起,从用户组织树中选择几个参与人一同办理任务,如果用户任务设置了按照并行的方式处理,那么将一次创建多个(和选择的人数量相等)实例,并按照选择参与人的顺序依次把任务分配assignee给参与人。如果按照顺序的方式执行任务,首先会创建一个任务实例分配给第一个参与人,只有第一个参与人办理完任务之后才会创建第二个任务实例、第三个任务实例……,并依次按照参与人的顺序设置任务的办理人。
顺序方式办理 :顺序办理也可以称作排队办理,只有一个人办理完后面的人才可以继续办理。
并行方式办理
设置结束条件 :可以根据不同的比例提前结束会签completionCondition

###审批意见
审批意见是工作流引擎中一个不可缺少的模块,流程变量可以保存流程处理过程中的中间状态(一般用于条件判断),审批意见可以保存每隔任务(一般指用户任务)办理时产生的意见。 Activiti在TaskService接口中定义了3个意见有关的方法:
1)创建意见:addComment(String taskId, String processInstanceId, String Message)
2) 根据流程实例ID获取意见:getProcessInstanceComments(String processInstanceId)
3) 根据任务ID读取意见:getTaskAttachements(String taskId)

##子流程与调用活动
在代码中,一个方法的功能过多时会拆分为多个方法,对于流程设计也是如此,可以从业务层面抽象考虑,把不同阶段的任务抽取出来作为一个子流程subprocess处理,如此当业务发生变化时只需要把更改聚焦在不同的子流程上即可,主流程负责串联(输出流)多个子流程。子流程也是一个完整的流程,有启动事件、用户任务、输出流以及结束事件等。

我们在开发时经常会使用很多第三方的插件来完成特定功能,例如利用POI处理Excel,一般不会自己去写处理Excel的代码而是利用现有的通用组件完成。在实际业务中也经常会有这样的需求,对于财务工作中的付款流程,付款的步骤基本固定,有申请、审批、出纳付款等节点,如果一个系统中有多个地方需要付款,那就需要在每个业务流程中设计重复的付款流程(或者作为一个子流程)。这样设计明显有弊端——重复且难以维护。调用活动Call Activity正是用来解决业务流程中重复设计的问题,只要设计好一个通用(或共用)的流程后由其他流程引用即可,当通用的部分变动时,业务流程无需更改,仅更改通用流程即可。

###子流程 对于单个流程来说,默认表ACT_RU_EXECUTION(运行时执行实例表)的ID_字段和PROC_INST_ID字段的值是相同的,如果一个流程包含子流程,调用活动,多实例的等活动类型,有主流程触发(自动启动)的Execution对象是附属于主流程的,通过设置Execution记录的PARENT_ID_字段的值为主流程实例的ID作为维护关系的条件。

子流程可以“共享”主流程的所有变量,而且子流程设置的变量可以以主流程的执行实例ID作为依据,所以子流程在获取数据时使用主流程的执行实例ID(子流程对应的执行实例的PARENT_ID_字段值)就可以获取到主流程的变量。

###调用活动
如果说子流程是一个类中的一个private方法,只能被当前类调用,那么调用活动就更上一层,把一个通用的方法提取到一个独立的类中供所有的类使用。

与子流程不同:
1)调用活动是以“引用”的方式把一个流程作为主流程的一个活动,当输出流到达调用活动时引擎会自动启动一个独立的流程实例,并把主流程的执行实例作为上级执行实例;
2)使用callActivity代替了subProcess,使用属性calledElement的值定义了外部流程的流程ID,使用activiti:in标签定义了2个输入类型的变量,这样独立的付款流程就可以使用target属性的值作为变量名获取变量,因为调用活动不能读取调用方的变量,必须通过activiti:in显示地指定;
3)在表ACT_RU_EXECUTION中是以SUPER_EXEC_字段来建立主流程和调用活动之前的上下级关系;
4)历史流程表ACT_HI_PROCINST表通过SUPER_PROCESS_INSTANCE_ID_字段来建立主流程和调用活动之前的上下级关系

##事件 ###定时启动事件
在什么时候创建定时任务? 答案是在部署流程之后,引擎对部属的流程定义做一些初始化的工作,其中就包含了对定时作业的注册(插入一条定时作业记录),还有对消息事件的注册等等。

定时启动事件可以按照预设时间启动是因为引擎不断刷新数据库表ACT_RU_JOB的记录,根据时间匹配作业,命中之后就执行作业。

ACT_RU_JOB表的主要字段说明:
1)TYPE_ :作业类型,有message和timer两种类型;
2)RETRIES_ :触发失败后最大重试次数,也可以通过调用ManagementService#setJobRetries方法设置;
3)DUEDATE_ :执行时间。引擎正是讲此字段与当前时间进行比较,相同或已超过则执行作业;
4)HANDLER_TYPE_ :作业的处理类型。对于每一种类型都有对应的处理器handler,目前引擎支持的类型有:event事件,timer-start-event定时启动事件,timer-transition边界定时事件,timer-intermediate-transition定时中间事件,async-continuation异步执行的作业
5)HANDLER_CFG_ :作业的目标,和HANDLER_TYPE_联合起来决定执行哪个流程定义的哪个作业处理类型,对于定时启动事件来说一般就是流程定义ID了。

###消息启动事件
在部署流程之后引擎会在初始化中处理消息事件,把消息的类型注册到数据库(ACT_RU_EVENT_SUBSCR),在流程执行过程中遇到了消息类型事件或通过API触发消息事件会从该表读取数据,并且根据消息的属性调用消息处理器。

ACT_RU_EVENT_SUBSCR表的主要字段说明:
1)EVENT_TYPE_ : 事件类型。message表示消息类型;
2)EVENT_NAME_ : 消息名称。 触发消息时引擎会根据消息名称参数和这个字段进行匹配;
3)EXECUTION_ID_ :实例执行ID。如果一个流程以消息启动事件引导,则此字段为空,如果在流程允许中注册了消息事件,则此字段保存流程执行ID;
4)PROC_INST_ID :流程实例ID。同EXECUTION_ID_,只不过保存的是流程实例ID(与EXECUTION是一对多的关系);
5)ACTIVITY_ID :活动ID。如果根据字段EVENT_NAME_匹配到消息就应该触发哪个活动;
6)CONFIGUATION_: 消息的配置信息。对于消息类型来说这里保存的是流程定义ID

当调用startProcessInstanceByMessage方法时,根据匹配规则就能触发消息启动事件,从而启动一个流程实例。

###结束事件
正常结束的流程,历史任务的deleteReason是completed,由于终止结束事件而引起流程实例结束执行的,历史任务的deleteReasion是deleted

###边界事件
消息边界事件、信号边界事件的cancelActivity:
true:在消息边界事件触发后取消已注册的消息事件;
false:在消息边界事件触发后仍然保留已注册的消息事件,可以再次触发;

##用户任务与附件
###用户任务 ####更改用户任务的属性 到期时间Task#setDueDate,优先级Task#setPriority

####任务相关人员 Task#setOwner,Task#setAssignee
1)拥有人:在流程处理过程中产生的用户任务,其拥有人属性为空,可以通过调用API方式更改用户任务的拥有人;
2)办理人:如果将一个任务直接分配给某一个用户,则这个用户就是任务的办理人;如果用户包含在候选人列表中或属于候选组中,并签收了该任务,此时该用户就是该任务的办理人;
3)参与人: 可以为用户列表添加不同类型的人员参与该任务办理,例如添加一个用户参与该任务的贡献者(根据任务内容给出办理意见,可以将意见以批注的方式分享给参与人)。为任务添加参与人实际上是向表ACT_RU_IDENTITYLINK中插入一条数据;

####反签收任务 反签收是相对于签收动作来说,可以把已经签收的任务任务的办理人置空,这样任务又还原到未签收的状态,此功能对误签收的情况很有用。

反签收任务的API和签收任务的相同,唯一不同是在签收任务时需要传递任务ID和用户ID,而反签收只需要传递任务ID,用户ID参数以null代替即可。

注意:如果用户任务没有相关候选人与候选组,只想反签收动作会导致任务无人认领。

####候选人&候选组
通过TaskService#addUserIdentityLink(taskId,userId,identityLinkType)方法可以添加一个参与人,其中第三个参数identityLinkType支持多种参与人关系类型。引擎对于每一种参与人关系类型都有不同的处理方式:
1)assignee : 任务的办理人,不会向表ACT_RU_IDENTITYLINK中插入数据,和Task#setAssignee的功能一样(实际后台就是调用了这个方法后更新任务);
2)owner : 任务的拥有人,与assgnee一样,不插入数据仅仅调用Task#setOwner后更新任务;
3)candidate: 表示任务的候选(人或组),根据表中的2个字段(USER_ID_, GROUP_ID_)是否为空来判断是候选人还是候选组;
4)starter :如果在启动流程时设置了认证用户,则会向表ACT_RU_IDENTITYLINK中插入一条数据表示流程启动人;
5)participant :在添加候选人、候选组或者非引擎支持的关系类型时,引擎会以流程实例ID作为标志(仅设置PROC_INST_ID_字段值不设置TASK_ID_字段值)插入数据到表ACT_RU_IDENTITYLINK中,方便根据流程实例查询参与人数据。一般没有权限签收任务,仅提供参考意见;

###子任务 在办理任务时可能会遇到需要把任务分解的情况,例如拆分出多个子任务交给不同的人办理,在Activiti中可以通过TaskService接口创建子任务或者根据父任务查询子任务。

可以继续在子任务中添加子任务,最终形成一颗树状结构。

引擎为提高运行速度把流程数据状态划分为运行中和历史(归档)2种类型,每一种状态对应不同的数据表,在一个用户任务执行完成后将该任务从运行时任务表ACT_RU_TASK中删除,并设置历史任务ACT_HI_TASKINST表的结束时间,因为这2张表的主键ID是相同的,所以可以根据运行时ID查询历史任务。

###附件 在流程流转过程中经常会附带一些文件,这些文件由不同的任务办理人上传。Acitiviti支持2种附件类型:
1)文件,以二进制流的方式保存到数据库
2)外部链接,把url直接保存到附件对象的url属性中

###改进意见列表 意见列表是为了在任务办理时允许办理人、候选人、参与人发表意见。除了用户自行添加意见之外,引擎还会自动把一些事件记录到意见列表。

ACT_HI_COMMENT表的一些字段:
1)TYPE_ :值为comment表示手动添加的任务办理意见,值为event表示由其他操作自动插入作为操作记录存在;
2)ACTION_ :记录每一条记录的动作类型,AddComment表示手动添加的意见,AddAttachment表示记录是在创建附件时由引擎自动创建。
3)MESSAGE_ :操作动作,例如,当动作为AddUserLInk且消息为jenny_|_candidate时,表示用户jenny被添加到任务的候选人列表。

###任务委派 任务委派是一个任务本来分配给用户A(委派人),但是A由于某些原因不能处理任务,可以把这个任务委派给用户B(被委派人)代理,在用户B处理完成后将任务再次回归给用户A

© 著作权归作者所有

v1-alpha

v1-alpha

粉丝 6
博文 64
码字总数 78948
作品 0
厦门
程序员
私信 提问
《Activiti实战》摘抄&笔记3

Query API简介 Activiti的查询API: 1)标准查询 :在以Java对象的方式通过创建一个指定类型的Query对象(实现Query接口)后用链式编程的方式设置查询参数。弊端:不能支持复杂的查询,比如多张...

v1-alpha
2016/07/05
286
0
Eclipse安装Activiti Designer 5.14.1插件错误处理

由于工作中需在eclipse开发环境下集成activiti插件,中间碰到插件不能安装的问题,特记录如下: 一、环境 1、eclipse 4.3.0 2、Activiti Designer 5.14.1 二、Activiti Designer 5.14.1插件安...

again-Y
2014/04/13
8.5K
0
读书笔记博客实战之搜索引擎索引和流量涨跌策略分析[图]

写在前面:最近百度动作频繁,变化十分大,以至于很多网站都出现了流量的大范围波动,引起了站长们的思考和分析猜测,但通过数据来分析是最可靠的观点,那么我们今天就来分析一下这几天百度在...

原创小博客
2018/05/17
8
0
推荐csdn里的几篇activiti基础入门及提高的博客

昨天有个网友加qq询问我有没有非maven搭建的activiti项目的demo,因为我博客中写了一个用maven,我当时没有,于是晚上回家尝试了一下,结果比较容易就实现了。 之后和那个网友聊了一下,他说...

涂宗勋
2016/04/20
338
0
activiti学习笔记2-构建流程引擎

一,本节概要 由学习笔记1中的最简单入门实例可以知道,activiti实际上就是提供了一系列服务组件,来完成对流程的管理与控制,如图,在之后的学习中,基本上就是围绕这个图来学习的: 二,构...

安世博
2014/06/14
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

前端面试题汇总

一. HTML常见的兼容性 1.HTML5 标签在低版本浏览器不兼容 解决办法:使用html5shiv库,引入下列语句 <!--[if lte IE 8]> <script src="https://cdn.bootcss.com/html5shiv/r29/html5.js"></sc......

蓝小驴
33分钟前
7
0
OSChina 周四乱弹 —— 我气的脸都黑了!

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 小小编辑推荐《Red Battle》- 高橋李依 / 豊崎愛生 《Red Battle》- 高橋李依 / 豊崎愛生 手机党少年们想听歌,请使劲儿戳(这里) @丶Lion ...

小小编辑
46分钟前
617
22
找OSG教程, B站就有

https://www.bilibili.com/video/av64849038?from=search&seid=11632913960900279653

洛克人杰洛
今天
5
0
学习记录(day07-Vue组件、自定义属性、自定义事件)

[TOC] 1.1.1什么是组件 一个vue文件就是一个组件 组件将html标签/css样式/对应JS打包成一个整体,也可以理解钻进一个具有样式和特效的自定义标签。 一、编写组件(提供方)<template> <di...

庭前云落
今天
5
0
使用Prometheus监控SpringBoot应用

通过之前的文章我们使用Prometheus监控了应用服务器node_exporter,数据库mysqld_exporter,今天我们来监控一下你的应用。(本文以SpringBoot 2.1.9.RELEASE 作为监控目标) 编码 添加依赖 使...

JAVA日知录
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部