Activiti框架學習記錄-01
本篇主要是Activiti工作流框架的學習記錄,以及對於該框架的基本使用和一些淺顯的理解:
- 1、工作流框架基本概念
- 2、在eclipse中使用工作流框架
- 3、創建工作框架
- 4、使用框架提供API,操作框架實現業務邏輯
1、工作流框架基本概念(摘自百度百科)
- 工作流(Workflow),就是“業務過程的部分或整體在計算機應用環境下的自動化”,它主要解決的是“使在多個參與者之間按照某種預定義的規則傳遞文檔、信息或任務的過程自動進行,從而實現某個預期的業務目標,或者促使此目標的實現”。
- 工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,並按照在系統中預先定義好的工作流邏輯進行工作流實例的執行。工作流管理系統不是企業的業務系統,而是爲企業的業務系統的運行提供了一個軟件的支撐環境。
- 常見的工作流框架:JBPM4.4、activiti5.13、OSWorkFlow;
2、在eclipse中使用工作流框架
1、可以離線安裝插件,將activit文件夾拷貝到eclipse-luna的安裝目錄下的
盤符:\Eclipse\eclipse_luna\dropins\ 文件夾下,重啓eclipse,進入eclipse後再Window下preference中出現Acitviti選項爲安裝插件成功,如下圖1所示:
並且勾選create process definition image when saving the diagram,這樣在我們保存一個流程的時候同時會保存一張png圖片;2、可以選擇在線安裝:
Name:Activiti BPMN 2.0 designer
Location:http://activiti.org/designer/update/;
等待一會兒安裝成功後操作以及界面同1所示;
當我們需要使用的時候,點擊new->others,如下圖2所示:
3、創建工作框架
- 1、建立表結構(兩種方式);
- 2、初步分析23張表的結構與意義;
- 3、框架中表的設計結構;
知識點分析1:表結構的建立
1)利用sql文件創建表,在我們activiti框架的目錄:
…\activiti-5.13\database\create\
執行sql文件,進入mysql命令行:
source E:\activiti-5.13\database\create\activiti.mysql.create.engine.sql
source E:\activiti-5.13\database\create\activiti.mysql.create.history.sql
source E:\activiti-5.13\database\create\activiti.mysql.create.identity.sql
2)利用API創建表
步驟一:配置文件,使用默認的配置文件:文件必須在類路徑下,名稱必須爲activiti-context.xml
文件中bean的ID規定好的
<!-- activiti-context.xml 配置文件代碼-->
<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-day01 -->
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 注入數據源信息 -->
<property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///activiti-demo01"></property>
<property name="jdbcUsername" value="root" ></property>
<property name="jdbcPassword" value="root"></property>
<!-- 注入自動建表設置 -->
<property name="databaseSchemaUpdate" value="true"></property>
</bean>
<!-- 提供工廠bean,創建流程引擎對象 -->
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"></property>
</bean>
</beans>
//Java代碼片段-01-使用配置文件
@Test
public void test() {
//使用的是默認文件的創建規則
ProcessEngine processEngine =
ProcessEngines.getDefaultProcessEngine();
}
//Java代碼片段-02-不使用配置文件
//使用activit框架提供的自動創建表的方式創建23張表
/**
* 自動建表的方式
*/
@SuppressWarnings("unused")
@Test
public void test1() {
//創建一個流程引擎配置對象
ProcessEngineConfiguration configuration =
ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//設置數據源信息
configuration.setJdbcDriver("com.mysql.jdbc.Driver");
configuration.setJdbcUrl("jdbc:mysql:///activiti-day01");
configuration.setJdbcUsername("root");
configuration.setJdbcPassword("1234");
//設置自動建表的操作
configuration.setDatabaseSchemaUpdate("true");
//使用配置對象創建一個流程引擎對象
ProcessEngine processEngine = configuration.buildProcessEngine();
}
知識點分析2:初步分析23張表的結構與意義
Activiti的後臺是有數據庫的支持,所有的表都以ACT_開頭。 第二部分是表示表的用途的兩個字母標識。 用途也和服務的API對應。
ACT_RE_*: ‘RE’表示repository。 這個前綴的表包含了流程定義和流程靜態資源 (圖片,規則,等等)。
ACT_RU_*: ‘RU’表示runtime。 這些運行時的表,包含流程實例,任務,變量,異步任務,等運行中的數據。 Activiti只在流程實例執行過程中保存這些數據, 在流程結束時就會刪除這些記錄。 這樣運行時表可以一直很小速度很快。
ACT_ID_*: ‘ID’表示identity。 這些表包含身份信息,比如用戶,組等等。
ACT_HI_*: ‘HI’表示history。 這些表包含歷史數據,比如歷史流程實例, 變量,任務等等。 ACT_GE_*: 通用數據, 用於不同場景下。
知識點分析3:初步分析23張表的結構與意義
Activiti的後臺是有數據庫中表的設計結構:
4、使用API操作工作流框架
初步模擬 流程 使用代碼片段如下:
1、畫圖:畫出流程圖
2、部署流程
1)部署流程定義
/**
* 初步模擬一個請假流程
* 1、部署流程定義
* 意義:將設計流程圖插入到數據庫中
*/
@Test
public void test4() {
//流程部署定義
//部署構建器,用於加載流程定義文件,部署流程定義
DeploymentBuilder deploymentBuilder =
processEngine.getRepositoryService().createDeployment();
//加載流程定義文件(bpmn、png)
deploymentBuilder.addClasspathResource("demo01.bpmn");
deploymentBuilder.addClasspathResource("demo01.png");
//返回部署對象
Deployment deployment = deploymentBuilder.deploy();
//常看當前的流程部署ID
System.out.println(deployment.getId());
}
2)查詢流程定義
// 查詢流程定義
@Test
public void test5() {
//流程定義查詢對象,操作的數據表act_re_prodef
ProcessDefinitionQuery query =
processEngine.getRepositoryService().createProcessDefinitionQuery();
//查詢到流程定義(流程定義表的而查詢)
//可以添加過濾條件
query.processDefinitionNameLike("請假流程");
//添加排序條件
query.orderByProcessDefinitionVersion().desc();
List<ProcessDefinition> list =
query.listPage(0, 1); // 分頁查詢
//流程定義對象的遍歷
for (ProcessDefinition processDefinition : list) {
String id = processDefinition.getId();
String name = processDefinition.getName();
int version = processDefinition.getVersion();
String deploymentId = processDefinition.getDeploymentId();
String resourceName = processDefinition.getResourceName();
System.out.println(id + "\t" + name + "\t" + version);
System.out.println(deploymentId + "\t" + resourceName);
}
}
3)根據流程定義的ID查詢實例
// act_ac_execution:存放的當前啓動的實例信息
// act_ru_task: 存放當前產生的任務(整個流程向下推進十分重要)
@Test
public void test6() {
String processDefinitionId = "qjlc:4:304"; //流程定義ID自己根據數據庫表中數據修改
ProcessInstance processInstance =
processEngine.getRuntimeService().startProcessInstanceById(processDefinitionId);
System.out.println(processInstance.getId());
}
4)查詢個人任務行爲
@Test
public void test7() {
//任務查詢對象,查詢任務表
TaskQuery query =
processEngine.getTaskService().createTaskQuery();
//添加過濾條件,根據任務的辦理人過濾
query.taskAssignee("張三");
List<Task> list = query.list();
for (Task task : list) {
System.out.println(task.getId() + "====" + task.getName());
}
}
4)辦理個人任務行爲
@Test
public void test8() {
String taskId = "1804"; // 任務ID,根據數據庫中task表中的數據進行修改
//自動推向到下一個任務人
processEngine.getTaskService().complete(taskId);
}
5)清理數據庫activiti表中的所有數據
@Test
public void test() {
DeploymentQuery query = processEngine.getRepositoryService().createDeploymentQuery();
List<Deployment> list = query.list();
for (Deployment deployment : list) {
//完全清理數據,級聯清理數據
processEngine.getRepositoryService().deleteDeployment(deployment.getId(), true);
}
}
流程實例的操作(代碼爲了保證完整性的功能與上述代碼功能會有部分重複)
1)首先聲明一個流程操作引擎,基本在整個框架的聲明週期中都會有所使用
//在項目中可以使用spring的注入技術進行處理,現在暫時使用普通方法
ProcessEngine pe = ProcessEngines.getDefaultProcessEngine();
2)部署流程定義
* 方式一:加載單個的流程定義文件
* 方式二:加載zip壓縮文件(將bpmn文件以及png文件進行打包爲process.zip)
@Test
public void test1() {
DeploymentBuilder deploymentBuilder =
pe.getRepositoryService().createDeployment();
// ZipInputStream zipInputStream_file = null;
// 方式一:加載單個流程定義文件
// deploymentBuilder.addClasspathResource("demo01.bpmn");
// deploymentBuilder.addClasspathResource("demo01.png");
// Deployment deployment = deploymentBuilder.deploy();
// 方式二:加載zip壓縮文件PS: 只支持zip
// Web項目中使用該方式
// try {
// zipInputStream_file = new ZipInputStream(new FileInputStream(new File("d:\\process.zip")));
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
ZipInputStream zipInputStream
= new ZipInputStream(this.getClass().getClassLoader().getResourceAsStream("process.zip"));
deploymentBuilder.addZipInputStream(zipInputStream);
deploymentBuilder.name("部署名稱測試");
Deployment deployment = deploymentBuilder.deploy();
String id = deployment.getId();
System.out.println(id);
}
3)查詢部署信息,查詢的通用寫法
pe.getXXXService().createXXXQuery().list()
@Test
public void test2() {
// pe.getRepositoryService().createDeploymentQuery().list();
// pe.getRepositoryService().createProcessDefinitionQuery().list();
// pe.getRuntimeService().createProcessInstanceQuery().list();
// pe.getTaskService().createTaskQuery().list();
// pe.getHistoryService().createHistoricActivityInstanceQuery().list();
List<Deployment> list = pe.getRepositoryService().createDeploymentQuery().list();
for (Deployment deployment : list) {
System.out.println(deployment.getId() + "\t" + deployment.getDeploymentTime());
}
}
3)刪除部署信息
// 刪除部署信息
@Test
public void test3() {
//刪除deploymentId爲501的部署信息數據,同樣會影響幾張表
String deploymentId = "501";
//是否級聯刪除(會刪除更多的表)
boolean cascade = true;
pe.getRepositoryService().deleteDeployment(deploymentId,cascade);
}
3)查詢流程定義數據
@Test
public void test4() {
List<ProcessDefinition> list = pe.getRepositoryService().createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
System.out.println(processDefinition.getId() + "\t" +
processDefinition.getKey() + "\t" +
processDefinition.getResourceName() + "\t" +
processDefinition.getVersion());
}
}
4) 刪除流程定義數據,通過刪除部署信息達到刪除流程定義的目的
@Test
public void test5() {
//刪除部署的時候會自動刪除流程定義
String deploymentId = "501";
pe.getRepositoryService().deleteDeployment(deploymentId);
}
5)查詢相關
/**
* 查詢最新版本的流程定義數據
*/
@Test
public void test6() {
//查詢的是所有的
pe.getRepositoryService().createDeploymentQuery().list();
//查詢最新的
List<ProcessDefinition> list = pe.getRepositoryService().createProcessDefinitionQuery().latestVersion().list();
for (ProcessDefinition processDefinition : list) {
System.out.println(processDefinition.getVersion() + "\t" + processDefinition.getDeploymentId());
}
}
@Test
public void test7() {
//沒有提供過濾條件就需要自己來寫
ProcessDefinitionQuery query = pe.getRepositoryService().createProcessDefinitionQuery();
//按照version升序排列
query.orderByProcessDefinitionVersion().asc(); //排序的方法
List<ProcessDefinition> list = query.list(); //list展示
Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>();
for (ProcessDefinition processDefinition : list) {
map.put(processDefinition.getKey(), processDefinition);
}
System.out.println(map);
list = new ArrayList<ProcessDefinition>(map.values());
for (ProcessDefinition processDefinition : list) {
System.out.println(processDefinition.getName() + "\t" + processDefinition.getId());
}
}
/**
* 查詢一次部署的對應的流程定義文件名稱和輸入流
* @throws IOException
*/
@Test
public void test8() throws IOException {
String deploymentId = "1101"; // 部署ID
List<String> names = pe.getRepositoryService().getDeploymentResourceNames(deploymentId);
for (String name : names) {
System.out.println(name);
//文件輸入流(是用來讀取BLOB字段的文件的)
InputStream inputStream = pe.getRepositoryService().getResourceAsStream(deploymentId, name);
//讀取出數據
FileUtils.copyInputStreamToFile(inputStream, new File("d:\\" + name));
// byte[] bytes = new byte[1024];
// while(inputStream.read(bytes) != -1) {
// i++;
// inputStream.read(bytes);
// outputStream = new FileOutputStream(new File("d:\\" + name));
// outputStream.write(bytes);
// }
//
inputStream.close();
// outputStream.close();
}
}
/**
* 獲得圖片的輸入流
* @throws IOException
*/
@Test
public void test9() throws IOException {
//從頁面上獲取一個流程ID
String processDefinitionId = "qjlc:9:1404"; // 流程定義ID
InputStream inputStream = pe.getRepositoryService().getProcessDiagram(processDefinitionId);
FileUtils.copyInputStreamToFile(inputStream, new File("d:\\my.png"));
inputStream.close();
}
6)啓動流程實例
/**
* 啓動流程實例
* 方式一:根據流程定義的ID啓動實例
* 方式二:根據流程定義的key啓動實例 (建議使用,會自動選擇最新版本)
*/
@Test
public void test10() {
String processDefinitionId = "qjlc:7:1204"; // 流程定義ID
//不會管是不是最新的流程版本
//方式一:根據流程定義的ID啓動流程實例
ProcessInstance pi = pe.getRuntimeService().startProcessInstanceById(processDefinitionId);
System.out.println(pi.getId());
String processDefinitionKey = "qjlc";
//方式二:根據流程定義的key啓動流程
//會根據最新的流程進行啓動
ProcessInstance pi_ = pe.getRuntimeService().startProcessInstanceByKey(processDefinitionKey);
System.out.println(pi_.getProcessDefinitionId());
}
7)查詢流程實例
/**
* 查詢流程實例
*/
@Test
public void test11() {
//流程實例查詢對象,查詢表act_ru_execution
ProcessInstanceQuery query = pe.getRuntimeService().createProcessInstanceQuery();
List<ProcessInstance> list = query.list();
for (ProcessInstance processInstance : list) {
System.out.println(processInstance.getId()+"\t"+processInstance.getActivityId());
}
}
8)刪除流程實例
/**
* 刪除流程實例
*/
@Test
public void test12() {
String processInstanceId = "1601"; // 流程實例ID
String deleteReason = "不請假了"; // 刪除流程實例原因
//刪除一個流程實例
pe.getRuntimeService().deleteProcessInstance(processInstanceId, deleteReason);
}
9)查詢個人任務
/**
* 查詢個人任務
*/
@Test
public void test13() {
TaskQuery query = pe.getTaskService().createTaskQuery();
String assignee = "王五";
query.taskAssignee(assignee);
List<Task> list = query.list();
for (Task task : list) {
System.out.println(task.getId() + "\t" + task.getName());
}
}
10)辦理個人任務
/**
* 辦理個人任務
*/
public void test14() {
String taskId = "1509"; //注意此處數據必須存在於數據庫的taskId表中
pe.getTaskService().complete(taskId);
}