之前也讲到,流程文件是通过XML文件配置的,如下所示:
<definitions id="definitions"
targetNamespace="http://activiti.org/bpmn20"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn">
<process id="vacationRequest" name="Vacation request">
<startEvent id="request" activiti:initiator="employeeName">
<extensionElements>
<activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
<activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
<activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
extensionElements>
startEvent>
<sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />
<userTask id="handleRequest" name="Handle vacation request" >
<documentation>
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
documentation>
<extensionElements>
<activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
<activiti:value id="true" name="Approve" />
<activiti:value id="false" name="Reject" />
activiti:formProperty>
<activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>managementformalExpression>
resourceAssignmentExpression>
potentialOwner>
userTask>
<sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />
<exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
<sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}conditionExpression>
sequenceFlow>
<task id="sendApprovalMail" name="Send confirmation e-mail" />
<sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
<endEvent id="theEnd1" />
<sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}conditionExpression>
sequenceFlow>
<userTask id="adjustVacationRequestTask" name="Adjust vacation request">
<documentation>
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation}
documentation>
<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" />
<activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
<activiti:value id="true" name="Yes" />
<activiti:value id="false" name="No" />
activiti:formProperty>
extensionElements>
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>${employeeName}formalExpression>
resourceAssignmentExpression>
humanPerformer>
userTask>
<sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />
<exclusiveGateway id="resendRequestDecision" name="Resend request?" />
<sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}conditionExpression>
sequenceFlow>
<sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
<conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}conditionExpression>
sequenceFlow>
<endEvent id="theEnd2" />
process>
definitions>
这只一个流程文件,摘自Activiti用户手册
对于BPMN元素的介绍,可以看 工作流系列(2)-BPMN简介。
Activiti对于BPMN元素的支持,只列出最基本的元素
简单的介绍开始结束事件,其他的比如边界事件等暂不介绍
BPMN元素 | Activiti 类 | 配置文件表示 |
---|---|---|
开始事件 | StartEvent |
|
结束事件 | EndEvent |
|
活动包含任务、子流程
只介绍常用的,当然还有其他的比如:业务规则任务、接受任务等
BPMN元素 | Activiti 类 | 配置文件表示 |
---|---|---|
用户任务 | UserTask |
|
服务任务 | ServiceTask |
|
手工任务 | ManualTask |
|
还有比如:脚本任务 ScriptTask
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
script>
scriptTask>
<subProcess id="subProcess">
<startEvent id="subProcessStart" />
... other Sub-Process elements ...
<endEvent id="subProcessEnd" />
subProcess>
<callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />
BPMN元素 | Activiti 类 | 配置文件表示 |
---|---|---|
并行网关 | ParallelGateway |
|
排他网关 | ExclusiveGateway |
|
包容网关 | InclusiveGateway |
|
BPMN元素 | Activiti 类 | 配置文件表示 |
---|---|---|
顺序流 | SequenceFlow |
|
在顺序流中可以增加条件,比如
<sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
<conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}conditionExpression>
sequenceFlow>
Activiti的解析工作,就是将配置文件中的元素转换为对应的Java类,如果说Java类在对顶层,则配置文件就位于最底层,而在这两者中间就是转换器与解析器。
首先对于每一个元素都有公共的属性,比如id、name等,对于这些公共属性,我们可以将其提取到公共的方法中进行解析。但是每个元素都有自己独特的属性,所以Activiti为每一个元素都定义了解析器或转换器,以便当每个元素增添属性时,只需要修改特定的解析器就可以实现。
BpmnXMLConverter是转换的入口,它读取配置文件并进行循环解析,通过注册不同的转换器来转换不同的元素,而在转化器中通过自己解析或调用解析器解析元素,并最终构建BpmnModel对象。
很多元素都具有相同的构造,所以拥有一个公共的解析方式;拥有公共的扩展属性(ExtensionAttribute),这些使用同一个解析器循环处理。
元素 | Java类 | 转换器 | 备注 |
---|---|---|---|
endEvent | EndEvent | EndEventXMLConverter | |
startEvent | StartEvent | StartEventXMLConverter | |
businessRuleTask | BusinessRuleTask | BusinessRuleTaskXMLConverter | |
manualTask | ManualTask | ManualTaskXMLConverter | |
receiveTask | ReceiveTask | ReceiveTaskXMLConverter | |
scriptTask | ScriptTask | ScriptTaskXMLConverter | |
serviceTask | ServiceTask | ServiceTaskXMLConverter | |
sendTask | SendTask | SendTaskXMLConverter | |
userTask | UserTask | UserTaskXMLConverter | |
task | Task | TaskXMLConverter | |
callActivity | CallActivity | CallActivityXMLConverter | |
eventGateway | EventGateway | EventGatewayXMLConverter | |
exclusiveGateway | ExclusiveGateway | ExclusiveGatewayXMLConverter | |
inclusiveGateway | InclusiveGateway | InclusiveGatewayXMLConverter | |
parallelGateway | ParallelGateway | ParallelGatewayXMLConverter | |
complexGateway | ComplexGateway | ComplexGatewayXMLConverter | |
sequenceFlow | SequenceFlow | SequenceFlowXMLConverter | |
catchEvent | CatchEvent | CatchEventXMLConverter | |
throwEvent | ThrowEvent | ThrowEventXMLConverter | |
boundaryEvent | BoundaryEvent | BoundaryEventXMLConverter | |
textAnnotation | TextAnnotation | TextAnnotationXMLConverter | |
association | Association | AssociationXMLConverter | |
dataStoreReference | DataStoreReference | DataStoreReferenceXMLConverter | |
valuedDataObject | ValuedDataObject | ValuedDataObjectXMLConverter | |
alfrescoStartEvent | AlfrescoStartEvent | AlfrescoStartEventXMLConverter | |
alfrescoUserTask | AlfrescoUserTask | AlfrescoUserTaskXMLConverter |
解析器所在包是org.activiti.bpmn.converter.child
和org.activiti.bpmn.converter.parse
元素 | Java类 | 解析器 | 备注 |
---|---|---|---|
process | Process | ProcessParse | |
subProcess | SubProcess | SubProcessParser | |
bpmndi:BPMNEdge | GraphicInfo | BpmnEdgeParser | 解析的是顺序流等线段图形位置等信息 |
bpmndi:BPMNShape | GraphicInfo | BpmnShapeParser | 解析的是任务等非线段图形位置、宽高等信息 |
lane | Lane | LaneParser | |
pool | Pool | ParticipantParser | |
messageFlow | MessageFlow | MessageFlowParser | |
activiti:executionListener | ExecutionListener | ExecutionListenerParser | 执行监听器 |
activiti:taskListener | ActivitiListener | TaskListenerParser | 任务监听器解析 |
multiInstanceLoopCharacteristics | MultiInstanceLoopCharacteristics | MultiInstanceParser | 解析包括loopCardinality、isSequential、completionCondition等信息 |