Liferay7 BPM门户开发之2: BPMN 2.0 规范入门 (Activiti BPMN extensions)

本文详细介绍了BPMN2.0的核心概念,包括事件、顺序流、网关、任务等,并深入探讨了如何利用这些概念设计流程。同时,文章还介绍了流程初始化认证、流程数据及表单属性等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Liferay最大的问题是BPM弱,如果做企业开发,BPM必不可少,所以直入主题,做个BPMN2入门.

本文参考地址:http://activiti.org/userguide/index.html#bpmnConstructs

BPMN 2.0中的重要概念:

  • Events 事件 
  • Sequence Flow 顺序流
  • Gateways 网关
  • Tasks 任务
  • Sub-Processes and Call Activities 子流程
  • Transactions and Concurrency 事务并发
  • Process Initiation Authorization 初始化认证
  • Data objects 流程数据

其他相关项:

  • Form properties 表单属性
  • External form rendering 外部表单集成

1、Events

1、1 Timer Event Definitions

由时间触发的时间,用于

  • start event
  • intermediate event
  • boundary event

必须有确切的一个元素,分别是:

timeDate

<timerEventDefinition> <timeDate>2011-03-11T12:13:14</timeDate> </timerEventDefinition>

在确切的时间点执行

timeDuration

<timerEventDefinition> <timeDuration>P10D</timeDuration> </timerEventDefinition>

 从最后一个任务完成后10天开始执行

timeCycle

<timerEventDefinition>
  <timeCycle activiti:endDate="2015-02-25T16:42:11+00:00">R3/PT10H</timeCycle>
</timerEventDefinition>
或者变量形式:
<timerEventDefinition>
  <timeCycle>R3/PT10H/${EndDate}</timeCycle>
</timerEventDefinition>

循环3次,间隔10小时

也可以使用cron expressions :http://www.quartz-scheduler.org/documentation/

 

1.2 Signal Event Definitions

一个例子:https://github.com/chanjarster/activiti-learn/wiki/%E8%AF%A6%E8%A7%A3signal%20event

1.3 Message Event Definitions

想象一下,作为一个嵌入式的流程引擎(不是国内很多固化Hardcode式的流程引擎),Activiti关心的是实际从第三方应用系统接收的消息。这将是环境依赖和需要特定平台的活动。
比如:

  • 连接到JMS(java消息服务)队列
  • 处理一个WebService
  • REST请求
  • MQ队列的消息处理
  • XMPP消息监听
  • ......

总之,消息是和应用程序相关联的。

在您收到您的应用程序中的一个消息后,您必须决定该如何处理它。如果消息应该触发一个新的流程实例的开始,process instance的启动不应该使用runtimeService.startProcessInstanceByKey,在以下方法中选择:

  • ProcessInstance startProcessInstanceByMessage(String messageName);
  • ProcessInstance startProcessInstanceByMessage(String messageName, Map<String, Object> processVariables);
  • ProcessInstance startProcessInstanceByMessage(String messageName, String businessKey, Map<String, Object> processVariables);
<definitions id="definitions"
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:activiti="http://activiti.org/bpmn"
  targetNamespace="Examples"
  xmlns:tns="Examples">

  <message id="newInvoice" name="newInvoiceMessage" />
  <message id="payment" name="paymentMessage" />

  <process id="invoiceProcess">

    <startEvent id="messageStart" >
        <messageEventDefinition messageRef="newInvoice" />
    </startEvent>
    ...
    <intermediateCatchEvent id="paymentEvt" >
        <messageEventDefinition messageRef="payment" />
    </intermediateCatchEvent>
    ...
  </process>

</definitions>

有不同的方式来启动事件,Message Event Definitions 就非常有用了

例如订单可能来自call center ,也可以来自web shop

 

1.4 Start Events

开始事件总是捕捉型(Catching)的,比如一个消息接收,比如一个时间触发,总是有指定的触发。

<startEvent id="request" activiti:initiator="initiator" />

启动:

try {
  identityService.setAuthenticatedUserId("bono");
  runtimeService.startProcessInstanceByKey("request");
} finally {
  identityService.setAuthenticatedUserId(null);
}
1.5 None Start Event

一个无启动事件在技术上意味着启动过程实例的触发器是未指定的。而且没有子元素节点。

一个有启动表单的例子:

<startEvent id="request" activiti:formKey="org/activiti/examples/taskforms/request.form" />

图形是一个空心圆:

 

1.6 Timer Start Event

时间启动事件,是一个时钟在中间的圆:

1.7 Boundary Events

边界事件是catching型的,连接到一个活动(一个边界事件永远不会throwing)的事件。
这意味着,当活动正在运行时,事件正在侦听某种类型的触发器。当事件被捕获时,该活动被中断,顺序流下行。

<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport">
  <timerEventDefinition>
    <timeDuration>PT4H</timeDuration>
  </timerEventDefinition>
</boundaryEvent>

<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
          <messageEventDefinition messageRef="newCustomerMessage"/>
</boundaryEvent>

 

2. Sequence Flow

2.1 Conditional sequence flow

带有UEL条件表达式的顺序流

<sequenceFlow id="flow" sourceRef="theStart" targetRef="theTask">
  <conditionExpression xsi:type="tFormalExpression">
    <![CDATA[${order.price > 100 && order.price < 250}]]>
  </conditionExpression>
</sequenceFlow>

 

2.2 Default sequence flow

任务和网关都可以有默认顺序流。

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" default="flow2" />
<sequenceFlow id="flow1" sourceRef="exclusiveGw" targetRef="task1">
  <conditionExpression xsi:type="tFormalExpression">${conditionA}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="task2"/>
<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="task3">
  <conditionExpression xsi:type="tFormalExpression">${conditionB}</conditionExpression>
</sequenceFlow>

flow2就是默认顺序流,当所有条件不满足,则选择默认顺序流。

 

3 Gateways

 3.1 Exclusive Gateway

异或网关

     输入:只要有一个活动节点到达该网关那么就触发

     输出:有多个输出点时,只会触发一个

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1">
  <conditionExpression xsi:type="tFormalExpression">${input == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2">
  <conditionExpression xsi:type="tFormalExpression">${input == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3">
  <conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression>
</sequenceFlow>

3.2 Parallel Gateway

并行网关,可以有多个输入和输出(fork, join or both) ,实现AND逻辑

输入:该网关所有的输入节点都必须完成后才能触发该网关

输出:该网关的所有输出接点都将触发(除非转移条件不通过)

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<parallelGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" />
<sequenceFlow sourceRef="fork" targetRef="shipOrder" />

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<parallelGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

 

 3.3 Inclusive Gateway

Inclusive包容网关(Xor输入,And输出)

     输入:只要有一个活动节点到达该网关那么就触发该网关(同XOR输入)

     输出:该网关的所有输出接点都将触发(除非转移条件不通过)同AND输出

 

<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />

<inclusiveGateway id="fork" />
<sequenceFlow sourceRef="fork" targetRef="receivePayment" >
  <conditionExpression xsi:type="tFormalExpression">${paymentReceived == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="fork" targetRef="shipOrder" >
  <conditionExpression xsi:type="tFormalExpression">${shipOrder == true}</conditionExpression>
</sequenceFlow>

<userTask id="receivePayment" name="Receive Payment" />
<sequenceFlow sourceRef="receivePayment" targetRef="join" />

<userTask id="shipOrder" name="Ship Order" />
<sequenceFlow sourceRef="shipOrder" targetRef="join" />

<inclusiveGateway id="join" />
<sequenceFlow sourceRef="join" targetRef="archiveOrder" />

<userTask id="archiveOrder" name="Archive Order" />
<sequenceFlow sourceRef="archiveOrder" targetRef="theEnd" />

<endEvent id="theEnd" />

 

4. TASKS

 

 4.1 User Task

需要用户参与的任务

humanPerformer 方式,指定一个执行人

<userTask id='theTask' name='important task' >
    <humanPerformer>
      <resourceAssignmentExpression>
        <formalExpression>kermit</formalExpression>
      </resourceAssignmentExpression>
    </humanPerformer>
  </userTask>
potentialOwner 多个人或组
<userTask id='theTask' name='important task' >
    <potentialOwner>
      <resourceAssignmentExpression>
        <formalExpression>user(kermit), group(management)</formalExpression>
      </resourceAssignmentExpression>
    </potentialOwner>
  </userTask>

还有通过属性来设置

  • <userTask id="theTask" name="my task" activiti:assignee="kermit" />
  • <userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" />
  • <userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" />

4.2 Script Task

4.3 Java Service Task

4.4 Business Rule Task

业务逻辑任务,使用JBoss Drools 规则引擎来处理输入输出;

<process id="simpleBusinessRuleProcess">

  <startEvent id="theStart" />
  <sequenceFlow sourceRef="theStart" targetRef="businessRuleTask" />

  <businessRuleTask id="businessRuleTask" activiti:ruleVariablesInput="${order}"
      activiti:resultVariable="rulesOutput" />

  <sequenceFlow sourceRef="businessRuleTask" targetRef="theEnd" />

  <endEvent id="theEnd" />

</process>

4.5 Camel Task

camel.apache 规则引擎任务,一个例子

<process id="PingPongProcess">
  <startEvent id="start"/>
  <sequenceFlow id="flow1" sourceRef="start" targetRef="ping"/>
  <serviceTask id="ping" activiti:type="camel"/>
  <sequenceFlow id="flow2" sourceRef="ping" targetRef="saveOutput"/>
  <serviceTask id="saveOutput"  activiti:class="org.activiti.camel.examples.pingPong.SaveOutput" />
  <sequenceFlow id="flow3" sourceRef="saveOutput" targetRef="end"/>
  <endEvent id="end"/>
</process>

 
   
org.activiti.camel.examples.pingPong.SaveOutput类

@Override
public void configure() throws Exception { from("activiti:PingPongProcess:ping").transform().simple("${property.input} World"); }

测试代码:
@Deployment
public void testPingPong() {
  Map<String, Object> variables = new HashMap<String, Object>();

  variables.put("input", "Hello");
  Map<String, String> outputMap = new HashMap<String, String>();
  variables.put("outputMap", outputMap);

  runtimeService.startProcessInstanceByKey("PingPongProcess", variables);
  assertEquals(1, outputMap.size());
  assertNotNull(outputMap.get("outputValue"));
  assertEquals("Hello World", outputMap.get("outputValue"));
}
 
   

 

 

 

 

5. Sub-Processes and Call Activities 子流程

 子流程是嵌入式的,不可重用,必须从None Start Event开始

而Call Activities本身调用的就是完整的流程

 

7. Process Initiation Authorization 初始化认证

 

<process id="potentialStarter">
  <extensionElements>
    <activiti:potentialStarter>
       <resourceAssignmentExpression>
         <formalExpression>group2, group(group3), user(user3)</formalExpression>
       </resourceAssignmentExpression>
    </activiti:potentialStarter>
  </extensionElements>

  <startEvent id="theStart"/>
  ...
或
<process id="potentialStarter" activiti:candidateStarterUsers="user1, user2"
                               activiti:candidateStarterGroups="group1">
      ...

 


8. Data objects 流程数据

 

<process id="dataObjectScope" name="Data Object Scope" isExecutable="true">
  <dataObject id="dObj123" name="StringTest123" itemSubjectRef="xsd:string">
    <extensionElements>
      <activiti:value>Testing123</activiti:value>
    </extensionElements>
  </dataObject>
  ...

 


9. Form properties 表单属性

  • StartFormData FormService.getStartFormData(String processDefinitionId)
  • TaskFormdata FormService.getTaskFormData(String taskId)
<userTask id="task">
  <extensionElements>
    <activiti:formProperty id="room" />
    <activiti:formProperty id="duration" type="long"/>
    <activiti:formProperty id="speaker" variable="SpeakerName" writable="false" />
    <activiti:formProperty id="street" expression="#{address.street}" required="true" />
  </extensionElements>
</userTask>

表单属性 room 对应--〉 流程变量 room 类型: String
表单属性 duration 对应--〉 流程变量 duration 类型: java.lang.Long
表单属性 speaker 对应--〉 流程变量 SpeakerName. 它是TaskFormData对象.
表单属性 street 对应--〉 Java bean 属性 street定义在流程变量 address

<startEvent id="start">
  <extensionElements>
    <activiti:formProperty id="speaker"
      name="Speaker"
      variable="SpeakerName"
      type="string" />

    <activiti:formProperty id="start"
      type="date"
      datePattern="dd-MMM-yyyy" />

    <activiti:formProperty id="direction" type="enum">
      <activiti:value id="left" name="Go Left" />
      <activiti:value id="right" name="Go Right" />
      <activiti:value id="up" name="Go Up" />
      <activiti:value id="down" name="Go Down" />
    </activiti:formProperty>

  </extensionElements>
</startEvent>
<startEvent>
  <extensionElements>
    <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
    <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
    <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
  </extensionElements>
</userTask>

 

表单:


10. External form rendering 外部表单集成

 提交表单属性,第三方表单系统发送数据:

ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)

FormService.submitTaskFormData(String taskId, Map<String,String> properties)

获得属性,Acticiti接收处理数据:

  • StartFormData FormService.getStartFormData(String processDefinitionId) 
  • TaskFormdata FormService.getTaskFormData(String taskId).
本系统集:OA,HR,CRM,于一身。 OA部分: 个人办公:内部邮件、Internet邮件、短信息、手机短信、公告通知、新闻、投票、个人考勤、日程安排、工作日志、工作汇报、通讯录、个人文件柜、控制面板 工作流:印章管理、表单定义 、工作流管理(支持复制,WEB印章等强化应用)、新建工作、待办工作、工作查询、工作监控、归档工作、委托设置 综合行政:公告通知管理、新闻管理、物品管理、固定资产管理、图书管理、会议管理、车辆管理、组织机构信息 信息交流:内部消息、内部邮件、外部邮件、内部讨论区、互动聊天、网络硬盘、投票管理、文件传阅 、手机短信管理 人力资源管理:人事档案、考勤批示、考勤统计、薪资管理、培训记录 、奖惩记录、基础设置 销售管理:客户管理、客户忠诚度管理、产品信息、销售管理、供应商管理、统计分析、基础数据设置 项目管理:项目创建、项目浏览、项目公告、项目进度、项目资源、项目预算、任务计划、项目外包、项目利润、费用报销、报销管理、数据字典 档案管理:卷库管理、案卷管理、文件管理 、案卷借阅(案卷借阅,借阅审批)、档案统计 (借阅统计,案卷统计) 、档案销毁 知识管理:知识大类、知识小类、我的知识、知识排行、知识地图、知识检索、知识互动、知识审批、知识管理员 附件管理:万年历 、世界时间 、常用网址浏览、邮编区号、日常查询 系统管理:印章管理、红头文件管理、用户管理 、角色管理 、部门管理、职位管理、附件类型、系统日志、手机短信管理组织机构设置:包含单位管理、部门管理、用户管理、角色与权限管理 其他:工作台设置,在线人员(组织结构模式),全部人员(组织结构模式) HR人力资源部分 机构管理:分级树形管理模式,部门编制数,岗位编制数等 招聘管理:需求征集(工作流),招聘计划(工作流),招聘初选(登记),招聘面试(登记),人员录用,人才储备, 基础数据设置 人事资料: 1.人事档案:人事管理(基本信息,个人简历,学习经历,工作经历,社会关系,职称评定,执业资格) 查看明细包括(基本信息,个人简历,学习经历,工作经历,社会关系,职称评定,执业资格,证照资料,合同信息,保险记录,调动情况,奖惩情况,培训课程,培训考勤,考核记录),导入数据,生日查询,人事统计分析,部门编制分析。 群发手机短信 2.合同管理:合同信息管理,合同变更,合同续签,员工转正,合同信息报表 3.人事调动:员工调动,员工离职,员工复职,人员流动分析,离职人员分析 4.员工奖惩:奖惩管理,奖惩分析,奖惩报表。 5.证照管理:证照管理,证照分析 6.职称评定:职称管理,职称分析 7.基础数据设置 培训管理:培训计划,培训考勤,培训机构,培训课件,培训费用,培训绩效,培训协议,基础数据设置 考勤管理:考勤记录采集(采集进考勤记录),考勤记录,出勤管理,休假管理,加班管理,统计查询报表 绩效考核:考核类型,考核期间,考核等级,考核信息,考核查询,考核报表,考核统计分析 薪资福利:个人所得税 ,社会保险,计件工资,计时工资.,提成工资,工资计算,工资帐套管理,工资统计分析 企业文化:单位企业介绍,单位信息发布,劳动法规及政策, 基础数据设置 系统管理:用户管理,角色管理,附件类型,系统日志,数据备份还原,备份还原设置 系统提醒:系统提醒:正式合同到期,试用合同到期,保险到期,员工生日,证照到期,职称申报,招聘计划开始,需求计划开始,培训计划开始。 系统管理 CRM客户关系管理部分 客户管理:检测客户、我的客户、共享客户、客户联系人、客户关怀、工作报告、我的客户、回收站 客户监控:允许监控的客户、客户联系人、客户关怀、工作报告浏览、 客户转移 客户跟踪:待办事宜、交往记录、销售机会、报价记录、竞争对手、销售费用 客户跟踪监控:待办事宜、交往记录、销售机会、报价记录、竞争对手、销售费用 合同定单:合同/订单、交付计划 、交付记录 、回款计划 、回款记录 、开票记录 、销售出库 合同/订单监控:合同/订单、交付计划 、交付记录 、回款计划 、回款记录 、开票记录 、销售出库 客户服务:客服控制台 、QA库管理 、投诉处理 、客服记录 、客服数据显示方案 采购管理:采购订单 、交付计划 、交付记录 、付款计划 、付款记录 、付款发票 、采购入库 采购监控:采购订单 、交付计划 、交付记录 、付款计划 、付款记录 、付款发票 、采购入库 库存管理:库存列表 入库单 :采购入库、直接入库 ; 出库单 :销售出库、直接出库库存盘点、库间调拨、报损单、报溢单、仓库设置、库存初始化/清空/清零、库存流水账 市场管理:市场活动 、广告发布 、印刷品管理 印刷品管理 :印刷品领用 礼品管理 :礼品管理 、礼品领用 供应商:供应商管理 、联系人管理 财务管理:应收款 、应付款 、已收款 、已付款 、收款发票 、付款发票 、费用报销 统计分析 客户管理:客户种类 、客户行业 、客户关系等级、客户人员规模 、客户来源 、客户阶段 、客户价值评估 、客户信用等级 、 客户拥有人 、客户创建数量人员/月度统计 、客户创建数量种类/月度统计 、大客户top20(合同额) 、大客户top20(回款额) 销售跟踪 :交往记录类型 、交往记录人员/月度统计 、客户交往记录top10 、报价记录人员/月度统计 、销售机会月份统计 、 销售机会负责人分布 、负责人/机会状态统计 、负责人/机会阶段统计 、 机会来源分布 、机会可能性分布 、机会状态分布 、机会阶段分布 、预计签单月份统计 合同/订单:合同订单状态分布 、合同订单状态/金额分布 、合同订单拥有者/状态分布 、合同订单签约时间统计 、合同订单签约金额月份统计 、合同订单签约金额人员分布 、合同订单签约金额人员/月度统计 、合同订单签约数量人员/月度统计 、合同订单未尽收款金额按签约月份统计 、合同订单类型分布 、合同订单签约金额类型分布 、 回款月度统计 、 回款人员/月度统计 、回款分类/月度统计 、回款人员分布 、回款付款方式统计 、回款分类统计、回款计划月度统计 、回款计划人员/月度统计 、开票类型/月度统计 售后服务:投诉月度统计 、投诉紧急程度/月度统计 、投诉处理结果/月度统计 、客户投诉次数top10 、投诉类型分布 、客服类型分布、客服方式分布 、客服状态分布 、客服月度统计 、 客服类型/月度统计 、 客服方式/月度统计 、 客服状态/月度统计 、客服次数top10 采购管理:采购单数量分类分布 、采购单金额分类统计 、月度采购单数量 、月度采购单金额 、人员采购单数量 、人员采购单金额 、采购单数量人员/月度统计 、采购单金额人员/月度统计 、采购发票月度统计 、 付款月度统计 、付款人员/月度统计 、付款分类/月度统计 、付款人员分布 、付款方式统计 、付款分类统计 、付款计划月度统计 、付款计划人员/月度统计 费用管理:月度费用申报统计 、月度通过审核费用统计 、月度费用人员统计(通过审核) 、费用类别分布(通过审核) 、费用类别统计(通过审核) 、人员/费用类型统计(通过审核) 、客户费用(通过审核)top20 市场管理 :市场活动类型分布 、市场活动类型/月度分析 、广告媒体类型分布 库存管理:库存流水产品数量分布 、库存流水月度统计 系统管理 用户管理、角色管理 、 组织机构 、职位管理 、 系统日志 、产品设置 、监控设置 数据备份还原:数据备份 、数据还原 备份还原设置:备份数据库 、备份存放路径 手机短信:已发送短信 、等待发送短信 、发送失败短信 、接收短信 数据字典:客户种类 、客户行业 、客户关系等级 、客户人员规模 、客户来源 、客户阶段 、 联系人分类 、客户关怀类型 、待办事宜类型 、交往记录类型 、销售机会来源 、 销售机会阶段 、竞争对手能力 、销售费用类、付款方式 、 合同订单分类 、 采购分类 、回款记录分类 、票据类型 、QA库分类 、 投诉处理分类 、 服务类型 、服务方式 、市场活动类型 、广告投放类型 、供应商所属分类 、供应商信用等级 、 直接入库类型 、直接出库类型 其他 工作台设置,在线人员(组织结构模式),全部人员(组织结构模式)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值