流程设计器教程 --- # 1.开始事件和结束事件 --- 对应着流程的开始和结束。 > 应该保证每个分支都可以从开始走到结束 ## 开始事件 开始事件用来指明流程在哪里开始。开始事件的类型(流程在接收事件时启动, 还是在指定时间启动,等等),定义了流程如何启动。 > 一般使用第一个空的开始事件就可以了,需要手动启动流程 *属性*  * 初始化器 当流程启动时,把当前登录的用户保存到哪个变量名中,可以在表达式里直接引用该变量 * 表单属性 当执行到开始事件时,所有的流程变量都是可用的,但是可能需要一些用于表单展示的自定义变量,此时可以在表单属性中定义,将会保存到流程的`共享变量`区域  如图是`请假流程`的开始事件的表单属性,在这里定义的变量,在`工作流测试页面`会自动渲染成表单 支持以下的几种表单属性类型: * string (org.activiti.engine.impl.form.StringFormType) * long (org.activiti.engine.impl.form.LongFormType) * enum (org.activiti.engine.impl.form.EnumFormType) * date (org.activiti.engine.impl.form.DateFormType) * boolean (org.activiti.engine.impl.form.BooleanFormType) > 括号里是作为流程变量存储的对应JAVA类 表达式和变量 如果设置了`变量`,需要通过变量名来引用变量,表达式同理 > 默认则是把id作为变量名使用 * 必须 如果勾选了,提交表单时没有提供该属性则抛出异常 * 可读 不勾选则不会进行自动渲染显示,但是还是可以提交 * 可写 不够勾选,还提交该属性,也会抛出异常 ## 结束事件 结束事件表示(子)流程(分支)的结束。 结束事件都是触发事件。 这是说当流程达到结束事件,会触发一个结果。 结果的类型是通过事件的内部黑色图标表示的。 > 一般使用一个空的结束事件就行了,意味着到达事件时不会指定抛出的结果。 这样,引擎会直接结束当前执行的分支,不会做其他事情。 ### 自动结束流程(HAP 扩展特性) 当一个任务被拒绝时,绝大多数情况下,这个流程应该直接结束。 但在工作流中,`审批拒绝`和`审批同意` 仅仅是给变量赋的参数值不同而已,如果希望流程结束,应该加一个 `选择网关`,判断审批结果是否为 `拒绝` ,然后引导流程走向`结束事件`。 显然,这很繁琐,尤其是当流程中`人工任务`节点比较多时。 HAP 做了一个优化: > 如果一个`人工任务` 的下一个节点仍然是 `任务(Task 类型)`,那么 HAP 将会自动插入一个`选择网关`和`终止事件` 来自动做结束流程的操作 这个优化在流程的图上是看不出来的,用户完全无感知。 # 2.任务 --- 常用的是人工任务,和服务任务 ## 人工任务(UserTask)  ### 任务派遣 **指定审批人、组** 点击`任务派遣` 弹出对话框 <img width='600' src='/assets/usertask-assignment.png'/> 其中: * 指派对象 只能有一个人,可以点击`选择`按钮来从系统中选择员工 * 候选用户 可以添加多个,每个指定一个`员工工号` * 候选组 可以添加多个,每个指定一个`岗位代码` **动态审批人、组** 与 上面类似,不过动态的审批人和组不是选择的,而是通过表达式计算得来。 `表达式`有两种情况 * 引用变量 比如`${initiator}`, 其中`initiator` 就是一个变量 * 调用 service 方法 比如`${orgStructure.getDirector(initiator)}`,其中 `orgStructure` 是一个自定的用于工作流的 `bean`,参数则可以使用任意的变量、常量等 > `execution` 是一个固有的、特殊的变量,指代 `org.activiti.engine.delegate.DelegateExecution`,非常有用 关于自定义在工作流中用的 `bean`: HAP 提供一个 接口 `com.hand.hap.activiti.custom.IActivitiBean`。 实现这个接口并被定义注册为 bean,其中的任何 `public` 方法都可以在工作流表达式中直接调用。 默认 bean 的 名字就是引用名,也可以覆盖接口的默认实现,指定名称。 ### 表单的标识Key 用于在待办明细页面中,动态渲染页面,设置为表单html页面的路径 ### 表单属性 跟开始事件的表单属性一样 **审批动作** Hap 的工作流在审批的时候默认有两个标准的动作: * 同意(APPROVED) * 拒绝(REJECTED) 当审批者点击按钮以后,审批动作 id 会被保存到流程的`共享变量`区域。 key 为 `approveResult`,这个变量可以直接在表达式中使用。 ``` ${approveResult=='REJECTED'} ``` 流程设计时,可以控制这两个按钮显示的文本;也可以控制只显示其中的一个。 允许自定义额外的审批动作,自动动作的 id 同样会保存在 `approveResult` 变量中,通常需要流程显示处理(比如选择网关)。 <img width='920' src='/assets/custom-approve-action.png'/> ### 会签设置 会签通过设置`多实例`属性来实现,有串行和并行两种模式。 > 三条竖线表示实例会并行执行。 三条横线表示顺序执行。 <img width='920' src='/assets/activiti_parallel.png'/> `集合` 应该返回一个字符串数组,表示用户集合 > 并行执行 会立刻为所有集合成员创建任务实例 > 串行执行 会依次创建任务实例,完成一个才会创建下一个 `元素变量` 遍历用户集合的单个对象变量名称 > 任务派遣 设置${元素变量}即可 `完成条件` > activiti 标准会签,默认有 3 个参数, 可以作为结束条件考量依据. 分别是 * nrOfInstances(实例个数,根据集集合表达式中获取的对象个数确定) * nrOfCompletedInstances(已经完成的实例个数,比如已经同意或者拒绝的) * nrOfActiveInstances(还未完成的实例个数) > hap 自定义了两个: * nrOfApproved(同意的实例个数) * nrOfRejected(拒绝的实例个数) ## 服务任务(ServiceTask) 用来调用外部java类 有三种方式 ### 类名 在`类名`属性设置类的完整限定名 比如`com.hand.hap.activiti.demo.DemoServiceTask` 直 > 需要实现JavaDelegate接口 类只会初始化一次, 类似 servlet 的模式。 ### 代理表达式 执行解析代理对象的表达式,直接通过表达式确定代理对象 比如`$(demoServiceTaskDelegate)` > 参考com.hand.hap.activiti.demo.components.DemoServiceTaskDelegate 实现JavaDelegate接口和IActivitiBean 注意是用$符号,这是delegateExpression,与普通的表达式有区别 ### 表达式 可以调用指定方法 `#{demoServiceTaskDelegate.method1(execution,task2Output)}` # 3.网关 网关用来控制流程的流向 网关显示成菱形图形,内部有有一个小图标。 图标表示网关的类型 ### 单一网关 内部图标是一个“X” 当流程执行到这个网关,所有外出顺序流都会被处理一遍。 通过设置`跳转条件`控制流程走向。 > 比如 ${approveResult == 'REJECTED'},表示拒绝后的流程走向。 可以设置`默认跳转`,当其他所以顺序流的跳转条件都返回false时触发。 > 注意如果多个顺序流的条件结果为true,单一网关只会选择一个执行。 ### 并行网关 内部是一个“+”图标 并行网关的功能是基于进入和外出的顺序流的: * 分支: 并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。 * 汇聚: 所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。 注意,如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。 与其他网关的主要区别是,并行网关*不会解析条件*。 即使顺序流中定义了条件,也会被忽略。 >参考[Activiti5.16中文手册](http://www.mossle.com/docs/activiti/index.html)