一、基本介紹
本人是個資料控,學習某項技術總要把這項技術的所有資料都蒐羅起來,綜合的去學習,慢慢的去啃。學習Activiti已經有2個月了,現就一些基本心得作一些記錄,有寫錯的地方還望大神指正,畢竟還是個小白。
目前關於activiti的書籍,市面上有三本,主要是瘋狂軟件楊恩雄編著的《瘋狂Activiti工作流》,閆洪磊的《Activiti實戰》,冀正的《Activiti權威指南》,個人感覺,三者都有所長,學習順序可以按照我列出的先後順序去學習,還是強烈推薦第二本,非常的實用。
視頻課程的話我只看過某站老雷和某馬的以及CSDN學院賴國榮老師講的課程。初學者還是比較推薦賴國榮老師的,看完之後可以看下老雷講的,都是帶有實戰項目的視頻。
二、繪製流程圖
做工作流,畫流程圖肯定是必不可少的。個人偏向於用eclipse安裝繪製流程圖插件去畫,插件的安裝方式前輩們都已寫過好多博客了,大家參考安裝即可。下面以一個生活中的例子,請假的審批來說說流程圖的繪製。
一個請假的審批流程,需要職員首先填寫請假單,然後交由所在部門的組長去審批,組長可以選擇同意或者是不同意,圖中一個X號是一個排他網關,代表流程會選擇其中一條路徑進行下去。如果選擇了同意請假,那麼下一步交由科長審批,科長審批完,該流程也就結束了。如果組長不同意請假,流程會走到“職員修改或放棄”,職員同樣可以自己是修改我的請假請求還是直接放棄申請。如果放棄申請,那麼流程便走向結束,如果修改申請,流程會返回填寫請假單的任務。這就是這個流程的大概走向。
下面說一下各個節點的需要注意的地方:
(一)啓動節點的配置
上述流程圖中啓動事件爲一個空啓動事件,一般情況下會在MainConfig中的Initiator屬性中設定一個變量,然後在項目中配合identityService.setAuthenticatedUserId方法,用來記錄流程的發起人。具體爲:
identityService.setAuthenticatedUserId("用戶ID")
(二)用戶任務的配置
流程圖中的黃色圓角矩形均爲用戶任務,有的地方也成爲“活動”,用戶任務主要配置的內容有如下內容
首先是職員填寫請假單任務:
1、general
id需要用戶自己爲該項“任務”(我覺得用活動更貼切一點,以防和數據庫表中的任務id混淆)定義一個id,name當然是起個名字了。
2、MainConfig
先說Assigne,意爲爲這個任務指定一個辦理人,填寫的是用戶的ID。在做這個實例之前,我準備瞭如下幾個用戶,用戶的信息保存在activiti流程引擎自動創建的25張表的act_id_user表中,用戶的設定可以在大家搭建完環境之後再設定。此處爲大家好理解故而提前說明。貼出我準備的用戶信息:
說回Assignee的設定,途中的任務辦理人用了${applyUserId}的方式引用了變量applyUserId的值,applyUserId的值前面已經說過是啓動流程的人人的ID,所以爲第一個任務的辦理人指定爲流程的發起人。聯想一下現實生活中的情景,我要發起一個請假流程,填寫請假單當然也是我自己了。
之後通過組長審批任務的設定我們對比看下Assignee
因爲組長通常是固定的一個人,所有此處我們之間把Assignee設定爲組長的ID,同理,科長也是之間設定科長的id。至於下面的候選用戶與候選用戶組,暫時不說。
(三)排他網關流程走向的控制
我們先之間看圖:
流程走向是通過設定條件來滿足,例如途中,直接在流程指向上設定某個條件,例如途中${groupLeaderApproved=='true'},當組長完成他的任務的時候,可以傳一個流程變量groupLeaderApproved進去,令groupLeaderApproved爲true,表明組長同意了請假,流程自動走到科長審批環節,同理,否定的設定${groupLeaderApproved=='false'}。基本需要注意的也就這些,像監聽器,表單日後再說。下面貼出流程圖的完成Xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="official_document" name="某局請假審批" isExecutable="true">
<startEvent id="startevent1" name="Start" activiti:initiator="applyUserId"></startEvent>
<userTask id="workerApply" name="職員填寫請假單" activiti:assignee="${applyUserId}"></userTask>
<userTask id="groupLeaderCheck" name="組長審批" activiti:assignee="groupLeader"></userTask>
<userTask id="sectionChiefCheck" name="科長審批" activiti:assignee="sectionChief"></userTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="workerApply"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="workerApply" targetRef="groupLeaderCheck"></sequenceFlow>
<sequenceFlow id="flow4" sourceRef="sectionChiefCheck" targetRef="endevent1"></sequenceFlow>
<exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow5" sourceRef="groupLeaderCheck" targetRef="exclusivegateway1"></sequenceFlow>
<sequenceFlow id="flow6" sourceRef="exclusivegateway1" targetRef="sectionChiefCheck">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${groupLeaderApproved=='true'}]]></conditionExpression>
</sequenceFlow>
<userTask id="usertask1" name="職員修改或放棄" activiti:assignee="${applyUserId}"></userTask>
<sequenceFlow id="flow7" sourceRef="exclusivegateway1" targetRef="usertask1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${groupLeaderApproved=='false'}]]></conditionExpression>
</sequenceFlow>
<exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
<sequenceFlow id="flow9" sourceRef="usertask1" targetRef="exclusivegateway2"></sequenceFlow>
<sequenceFlow id="flow10" sourceRef="exclusivegateway2" targetRef="endevent1">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${workerChangeApply=='false'}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow11" sourceRef="exclusivegateway2" targetRef="workerApply">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${workerChangeApply=='true'}]]></conditionExpression>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_official_document">
<bpmndi:BPMNPlane bpmnElement="official_document" id="BPMNPlane_official_document">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="90.0" y="220.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="workerApply" id="BPMNShape_workerApply">
<omgdc:Bounds height="55.0" width="131.0" x="220.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="groupLeaderCheck" id="BPMNShape_groupLeaderCheck">
<omgdc:Bounds height="55.0" width="105.0" x="450.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="sectionChiefCheck" id="BPMNShape_sectionChiefCheck">
<omgdc:Bounds height="55.0" width="105.0" x="710.0" y="210.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="930.0" y="220.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
<omgdc:Bounds height="40.0" width="40.0" x="600.0" y="217.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="137.0" x="552.0" y="330.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="exclusivegateway2" id="BPMNShape_exclusivegateway2">
<omgdc:Bounds height="40.0" width="40.0" x="600.0" y="440.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="125.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="220.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="351.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="450.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="815.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="930.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="555.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="600.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
<omgdi:waypoint x="640.0" y="237.0"></omgdi:waypoint>
<omgdi:waypoint x="710.0" y="237.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
<omgdi:waypoint x="620.0" y="257.0"></omgdi:waypoint>
<omgdi:waypoint x="620.0" y="330.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
<omgdi:waypoint x="620.0" y="385.0"></omgdi:waypoint>
<omgdi:waypoint x="620.0" y="440.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
<omgdi:waypoint x="640.0" y="460.0"></omgdi:waypoint>
<omgdi:waypoint x="947.0" y="459.0"></omgdi:waypoint>
<omgdi:waypoint x="947.0" y="255.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
<omgdi:waypoint x="600.0" y="460.0"></omgdi:waypoint>
<omgdi:waypoint x="285.0" y="459.0"></omgdi:waypoint>
<omgdi:waypoint x="285.0" y="265.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
三、基於SSM框架整合工作流的初始環境搭建
ssm搭建的過程我就不說了,大家應該都會,主要說一下整合Activiti,如果需要源碼我可以發出來供大家參考。
一、POM文件
<!-- 配置版本 -->
<properties>
<spring.version>4.3.17.RELEASE</spring.version>
<mysql.version>5.1.39</mysql.version>
<!-- 注意只能使用2.0以下的版本 -->
<activiti.version>5.22.0</activiti.version>
<mybatis.version>3.4.6</mybatis.version>
<!-- 注意只能使用2.0以下的版本 -->
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<!-- activiti的依賴 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- ssm集成的時候使用 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置編譯的jdk版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<!-- 指定source和target的版本 -->
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
二、Acitiviti的配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--配置activiti的主鍵生成器-->
<bean id="uuidGenerator" class="org.activiti.engine.impl.persistence.StrongUuidGenerator" />
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<!-- 數據源 -->
<property name="dataSource" ref="pooledDataSource" />
<!-- 配置事務管理器,統一事務 -->
<property name="transactionManager" ref="transactionManager" />
<!-- 設置建表策略 -->
<property name="databaseSchemaUpdate" value="true" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<!--
bean id repositoryService
RepositoryServicie repositoryService = processEngine.getRepositoryService();
-->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="formService" factory-bean="processEngine" factory-method="getFormService" />
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
</beans>
當然還有數據庫文件,log4j我就不貼了。下一篇我們說說各種服務