對於解析流程文件,Activiti使用的是流模式,在5.12.1之前使用的是推模式(SAX),而在此之後使用的拉模式(STAX)。
配置文件
之前也講到,流程文件是通過XML文件配置的,如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<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>management</formalExpression>
</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用戶手冊
BPMN2.0元素與Activiti的支持
對於BPMN元素的介紹,可以看 工作流系列(2)-BPMN簡介。
Activiti對於BPMN元素的支持,只列出最基本的元素
事件(Event)
簡單的介紹開始結束事件,其他的比如邊界事件等暫不介紹
BPMN元素 | Activiti 類 | 配置文件表示 |
---|---|---|
開始事件 | StartEvent | <startEvent id="startevent1" name="開始"></startEvent> |
結束事件 | EndEvent | <endEvent id="endevent1" name="結束"></endEvent> |
活動(Activity)
活動包含任務、子流程
任務(Task)
只介紹常用的,當然還有其他的比如:業務規則任務、接受任務等
BPMN元素 | Activiti 類 | 配置文件表示 |
---|---|---|
用戶任務 | UserTask | <userTask id="fillForm" name="填寫表單" /> |
服務任務 | ServiceTask | <serviceTask id="print" activiti:expression="#{printer.printMessage}" /> |
手工任務 | ManualTask | <manualTask id="myManualTask" name="Call client for more information" /> |
還有比如:腳本任務 ScriptTask
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
</script>
</scriptTask>
子流程
- 嵌入子流程 subProcess
<subProcess id="subProcess">
<startEvent id="subProcessStart" />
... other Sub-Process elements ...
<endEvent id="subProcessEnd" />
</subProcess>
- 調用子流程 callActivity
<callActivity id="callCheckCreditProcess" name="Check credit" calledElement="checkCreditProcess" />
網關
BPMN元素 | Activiti 類 | 配置文件表示 |
---|---|---|
並行網關 | ParallelGateway | <parallelGateway id="myParallelGateway" /> |
排他網關 | ExclusiveGateway | <exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" /> |
包容網關 | InclusiveGateway | <inclusiveGateway id="myInclusiveGateway" /> |
鏈接對象
BPMN元素 | Activiti 類 | 配置文件表示 |
---|---|---|
順序流 | SequenceFlow | <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" /> |
在順序流中可以增加條件,比如
<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等信息 |