Activiti概述
工作流概念
工作流(Workflow),指“業務過程的部分或整體在計算機應用環境下的自動化”。是對工作流程及其各操作步驟之間業務規則的抽象、概括描述。
通俗的說,流程(過程)就是多個人在一起合作完成某件事情的步驟,把步驟程式設計計算機能了解的形式,就是工作流。
工作流是研究一個群體如何在計算機的幫助下實作協同工作的,其主要解決的問題是:為了實作某個業務目标,利用計算機在多個參與者(Actor)之間按某種預定規則自動傳遞文檔、資訊或者任務(Task)。
【不使用工作流技術:】
從頭開始開發這個訂購流程的業務邏輯,我們需要:
- 每個活動點都需要開發互動頁面和背景處理程式
- 每個活動的流轉都需要硬性判斷下一步活動節點及其操作人
- 每次操作都需要維護業務資料和流程的相關資料
使用好處:
- 使用專門的流程資料系統,維護所有涉及流程流轉的資料。
- 提供“流程設計”工具,幫助使用者定義訂貨流程的模型,而且一般都提供了可視化的界面。
- 所有的流程都依靠流程引擎來處理,避免了需求更改與寫死之間沖突的産生。
- 工作流引擎還提供了衆多的API,可以很友善的将工作流的管理和業務操作完美結合。
工作流技術的優勢
-
降低開發風險
通過使用諸如活動、流轉、狀态、行為這樣的術語,使得業務分析師和開發人員使用同一種語言交談成為可能。優秀的流程設計模組化工具,甚至能使開發人員不必将使用者需求轉化成詳細設計文檔。
-
流程實作的集中統一
應對業務流程經常變化的情況,使用工作流技術的最大好處是使業務流程的實作代碼,不再散落在各式各樣的業務系統中。
-
加速開發
開發者不用再關注流程的參與者、活動節點的銜接、流轉控制……因為這些工作很多被工作流架構接管了。因而開發者開發起來更快、代碼出錯更少、系統更加容易維護。
-
提升對疊代開發的支援
如果系統中業務流程部分被寫死,就不容易更改,需求分析師就會花費很大的精力在開發前的業務分析中,并且希望一次成功。但可悲的是,在任何軟體項目開發中,這都很少能實作。工作流管理系統使得業務流程很容易部署和重新編排,業務流程相關的應用開發可以以一種“疊代/漸進”的方式推進,也就是說工作流技術在某種程度上支援“需求分析不必一次完全成功”。
工作流的技術特點
工作流隻管理流程,是不能完成業務操作的。換句話說,工作流是相對獨立的、通用的,與業務管理無直接關系。
比如費用報帳流程,工作流管理的是報帳的流程(誰申請,誰審批),費用報帳的業務(使用費用的原因,使用費用的時間,,)
工作流雖然與業務無直接關系,但是,在開發的時候,需要考慮和業務整合。
常見的工作流架構
Activiti、JBPM、OSWorkflow、ActiveBPEL、YAWL等。
Activiti的起源
Activiti是一套業務流程管理(BPM)架構,它覆寫了業務流管理、工作流、服務協助等領域,它是一個開源的(Apache許可2.0)、靈活的、易擴充的可執行流程語言架構。
Activiti是Alfresco軟體在2010年5月17日宣布啟動的一個開源項目,其創始人和首席架構師由業務流程管理BPM的專家 Tom Baeyens擔任。Tom Baeyens是JBoss jBPM的項目架構師。
提示:Jbpm4版本之後,該作者才做的Activiti,是以,Activiti很像jbpm4,理念又有點像hibernate。但是,jbpm5與4版本的差距比較大。
它是一項新的基于Apache許可的開源BPM平台,從基礎開始建構,提供支援新的BPMN 2.0标準。(直覺的認識就是XML)
Activiti提供了流程設計器,開發人員可以直接通過流程設計器直接畫出業務流程圖。
Activiti的持久層使用的Mybatis。(api将dao封裝了,無需會mybatis)
Activiti環境搭建
One minute version(官方Demo示範)
第一步:用管理者進去定制流程。
第二步:部署和啟動流程。
第三步:使用流程。
使用工作流系統需要三步:
1.畫流程圖(流程文檔xml定義)—管理者
2.部署到工作流的系統中—管理者
3.啟動流程,開始執行任務,直到任務結束。–使用者
建立Maven項目
Maven坐标(工作流引擎activiti-engine,日志實作slf4j-log4j12,資料庫驅動oracle,測試junit):
<properties>
<activiti.version>5.19.0.2</activiti.version>
<slf4j.version>1.7.5</slf4j.version>
<oracle.version>10.2.0.4.0</oracle.version>
<c3p0.version>0.9.1.2</c3p0.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>${oracle.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
初始化Activiti資料庫
建立一個測試類:
/**
* Activiti測試類
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class ActivitiTest {
//建立表:通過建立工廠(流程引擎:用來生成其他的服務api來具體操作)
@Test
public void testCreateTable(){
//1.得到引擎的配置對象:單伺服器使用
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//2.在引擎配置對象上設定相應的資料庫連接配接參數
processEngineConfiguration.setJdbcDriver("oracle.jdbc.driver.OracleDriver");
processEngineConfiguration.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
processEngineConfiguration.setJdbcUsername("bos");
processEngineConfiguration.setJdbcPassword("bos");
//設定自動建表
//三種參數值:
//false:隻是檢查表結構,但不建立也不更新。适合已經有表的時候用
//create-drop:啟動的時候檢查和建立表,引擎關閉的是的删除
//true:檢查表結構,如果表存在,則建立,如果表結構不一緻,則更新。---常用
processEngineConfiguration.setDatabaseSchemaUpdate(processEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
//擷取工作流引擎對象(單例)
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
System.out.println("====="+processEngine);
}
}
Activiti的核心
- ACT_RE_*: ‘RE’表示repository。 這個字首的表包含了流程定義和流程靜态資源 (圖檔,規則,等等)。
- ACT_RU_*: ‘RU’表示runtime。 這些運作時的表,包含流程執行個體,任務,變量,異步任務,等運作中的資料。 Activiti隻在流程執行個體執行過程中儲存這些資料, 在流程結束時就會删除這些記錄。 這樣運作時表可以一直很小速度很快。
- ACT_ID_*: ‘ID’表示identity。 這些表包含身份資訊,比如使用者,組等等。
- ACT_HI_*: ‘HI’表示history。 這些表包含曆史資料,比如曆史流程執行個體, 變量,任務等等。
- ACT_GE_*: ‘GE’表示general。通用資料, 用于不同場景下,如存放資源檔案。
- ACT_EVT_LOG:事件日志
ProcessEngine:流程引擎接口,是最核心的API類,其他的API類都由他而來。它是其他API産生的基礎!ProcessEngine對象,這是Activiti工作的核心。負責生成流程運作時的各種執行個體及資料、監控和管理流程的運作。
- RepositoryService 流程定義管理 操作 ACT_RE_* 資料表
- RuntimeService 流程執行個體管理 操作 ACT_RU_* 資料表
- TaskService 任務管理 操作 ACT_RU_TASK 資料表
- IdentitiService 認證管理 操作 ACT_ID_* 資料表
- HistoryService 曆史記錄管理 操作 ACT_HI_* 資料表
- ManagementService 定時任務管理,建立job,ACT_RU_JOB 資料表
- FormService 表單管理,生成動态任務表單頁面,某個字段存的資料
maven坐标
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
ApplicationContext.xml:
<!-- 流程引擎配置對象 -->
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 注入資料源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 自動建表 -->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
<!-- 流程引擎對象 -->
<bean id="processEngine" factory-bean="processEngineConfiguration" factory-method="buildProcessEngine"/>
流程文檔定義—畫流程圖
流程id(非常重要-将來程式裡面叫key—流程定義的唯一辨別),必須英文.
添加辦理人:
Bpmn檔案解讀:

流程定義管理
核心API
關于工作流的api,有個規律:要擷取某對象,都是createXxx;
如果是CreateXxx,擷取的就是xxx對象,該對象主要用來增删改對應的表。
如果是CreateXxxQuery,擷取的是xxxQuery對象,該對象主要用來查詢的。
加載流程文檔的時候,可以單獨加載文檔bpmn,工作流會自動生成一張圖檔存在資料庫。
但也可以兩個都加載,那麼工作流就不會自動生成圖檔,而使用你上傳的圖檔。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
locations="classpath:applicationContext.xml")
public class ActivitiTest {
//注入倉庫Service
@Autowired
private RepositoryService repositoryService;
//釋出流程:隻釋出流程圖,自動生成圖檔
@Test
public void deployment1(){
Deployment deployment = repositoryService.createDeployment()//擷取釋出對象
.addClasspathResource("diagrams/Leave.bpmn")//添加流程檔案
.name("請假流程1")//釋出的名字
.deploy();//釋出
System.out.println("釋出的編号:"+deployment.getId());
System.out.println("釋出的名稱:"+deployment.getName());
System.out.println("釋出的時間:"+deployment.getDeploymentTime());
}
//釋出流程:釋出流程圖和圖檔--第一種方法
@Test
public void deployment21(){
Deployment deployment = repositoryService.createDeployment()//擷取釋出對象
.addClasspathResource("diagrams/Leave.bpmn")//添加流程檔案
.addClasspathResource("diagrams/Leave.png")//添加流程圖檔
.name("請假流程21")//釋出的名字
.deploy();//釋出
System.out.println("釋出的編号:"+deployment.getId());
System.out.println("釋出的名稱:"+deployment.getName());
System.out.println("釋出的時間:"+deployment.getDeploymentTime());
}
//釋出流程:釋出流程圖和圖檔--第二種方法
@Test
public void deployment22() throws FileNotFoundException{
Deployment deployment = repositoryService.createDeployment()//擷取釋出對象
.addZipInputStream(new ZipInputStream(this.getClass().getClassLoader().getResourceAsStream("diagrams/Leave.zip")))
.name("請假流程22")//釋出的名字
.deploy();//釋出
System.out.println("釋出的編号:"+deployment.getId());
System.out.println("釋出的名稱:"+deployment.getName());
System.out.println("釋出的時間:"+deployment.getDeploymentTime());
}
}
ApplicationContext.xml:
<!-- 流程控制的相關service -->
<!-- 倉庫對象 -->
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"></bean>
工作流服務端自動生成的圖檔的亂碼問題解決方案:
解決方案1:
在流程引擎配置對象上面設定字型屬性:
<!-- 釋出流程生成圖檔是正常顯示中文 -->
<property name="activityFontName" value="宋體"/>
<property name="labelFontName" value="宋體"/>
解決方案2:
流程圖的圖檔在設計器中生成好,上傳到伺服器,不讓伺服器自動生成圖檔。
部署資訊查詢
//查詢部署表對象資料
@Test
public void queryDeployment(){
List<Deployment> list = repositoryService.createDeploymentQuery()
//條件查詢
.deploymentName("請假的流程部署")
.deploymentId("1")//根據id
.singleResult()//查詢出一條結果
.orderByDeploymenTime()//排序
.listPage(firstResult, maxResults)//分頁
.count()//統計
.list();
流程定義資訊查詢
@Test
//查詢流程定義的表的資料
public void queryProceeDefinition(){
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
// .processDefinitionKey(processDefinitionKey)//根據key來查詢
.list();
流程圖檢視
//查詢流程圖
@Test
public void findProcessDefinitionDiagram() throws IOException{
InputStream in = repositoryService.getProcessDiagram("LeaveProcess:1:4");
OutputStream out = new FileOutputStream("z:/Leave.png");
FileUtil.copyStream(in, out);
}
流程定義的删除-流程銷毀
//删除流程定義(通過部署id)
@Test
public void deleteProcessDefinition(){
repositoryService.deleteDeployment("1", true);
}
級聯和不級聯。
場景:如果流程已經開啟了,如果不使用級聯,則會抛出異常!(原因:定義表有外鍵關聯它),此時隻能用級聯。
流程執行個體管理
流程執行個體的啟動
- 根據流程定義的id來啟動:可以啟動指定的流程定義。
- 根據流程定義的key來啟動:自動選擇版本号最高(最新)的流程定義來啟動
- 根據消息的名字來啟動
//啟動流程執行個體
@Test
public void startProcessInstance(){
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("LeaveProcess");
}
applicationContext.xml配置:
<!-- 運作時Service -->
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
流程執行個體的查詢
//查詢流程執行個體
@Test
public void queryProcessInstance(){
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
.list();
}
流程目前節點的坐标
//查詢活動節點坐标
@Test
public void queryActiveNodeZuobiao(){
List<String> activeActivityIds = runtimeService.getActiveActivityIds("10001");
for (String activeActivityId : activeActivityIds) {
GraphicInfo graphicInfo1 = repositoryService.getBpmnModel("LeaveProcess:4:7504")
.getGraphicInfo(activeActivityId);//某活動節點的坐标
}
}
流程執行個體的删除(強行終止)
//流程執行個體的删除
@Test
public void deleteProcessInstance(){
runtimeService.deleteProcessInstance("LeaveProcess:4:7504", "不想請假了");
}
- 删除流程定義:可以級聯删除流程定義以及流程執行個體相關表資料。–管理者
- 删除流程執行個體:隻删除流程執行個體相關(運作時)表的資料,對流程定義沒有影響。-流程啟動者
任務管理
個人任務查詢(待辦任務查詢)
//個人任務查詢
@Test
public void queryPersionTask(){
List<Task> list = taskService.createTaskQuery()
.taskAssignee("張三")
.list();
}
個人任務辦理
//個人任務辦理
@Test
public void completePersonTask(){
taskService.complete("12504");
}
任務辦理完成
當end節點之前的節點辦理完成後,會自動完成end節點。目前流程執行個體都結束了。