JBPM(二)---JBPM工作流基本操作
流程定義的管理:
將定義業務流程,部署到 jbpm框架中 (流程定義 jpdl.xml 描述檔案)
通過gpd 外掛 先根據業務流程,繪製流程圖 (holiday.jpdl.xml 和 holiday.png )
流程定義部署 :
先獲得 ProcessEngine 物件,再獲得對應 Service (六個Service)
ExecutionService getExecutionService() // 流程例項管理
HistoryService getHistoryService() // 歷史記錄管理
IdentityService getIdentityService() // 使用者認證管理
ManagementService getManagementService() // 任務排程
RepositoryService getRepositoryService() // 流程定義管理
TaskService getTaskService() // 任務關聯
操作流程定義,需要使用 RepositoryService
deployment 將需要釋出到JBPM框架中流程檔案,新增到物件中
// 1、 先獲得流程引擎 (JBPM程式設計核心)
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、通過引擎獲得需要Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、釋出流程定義
NewDeployment deployment = repositoryService.createDeployment();
deployment.addResourceFromClasspath ("holiday.jpdl.xml");
deployment.addResourceFromClasspath("holiday.png");
deployment.deploy();
流程定義釋出,影響的資料表分析
JBPM的資料記錄採用流水號 id ,在 jbpm4_property 表中用來儲存下次操作的開始id, Value 初始化值是1, 每進行過一輪資料庫操作,記錄+10000
jbpm4_deployment 流程定義釋出表,每釋出一個流程,在該表插入1條記錄 ,DBID 就是流水號
jbpm4_lob 存放大資料(二進位制) 存放釋出流程定義檔案
jbpm4_deployprop 流程定義屬性表 ,每釋出一個流程,將流程屬性資訊儲存到該表
langid 是jpdl語言規範版本號、pdid 流程定義唯一標識、pdkey 流程定義關鍵字、pdversion 流程定義版本號
在繪製流程定義時,name值就是預設的key值 ,version每次釋出相同key ,version自動+1
釋出流程定義,在實際開發中,都是通過 zip壓縮包釋出
//釋出流程定義
NewDeployment deployment = repositoryService.createDeployment();
deployment.addResourcesFromZipInputStream(new ZipInputStream(new FileInputStream("holiday.zip")));
deployment.deploy();
流程定義查詢 :
通過 ProcessDefinitionQuery查詢流程定義資訊
ProcessDefinitionQuery processDefinitionQuery
= repositoryService.createProcessDefinitionQuery();
對 ProcessDefinitionQuery 新增查詢條件
processDefinitionId(processDefinitionId)
processDefinitionKey(key)
processDefinitionName(name)
processDefinitionNameLike(name)
page(firstResult, maxResults)
orderAsc(property)
orderDesc(property)
通過 指定屬性查詢,可以進行排序和分頁 查詢
List<ProcessDefinition> list = processDefinitionQuery
.orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION)
.page(0, 2).list();
根據釋出編號 和 資源名稱可以獲得 該流程相關資源
// 查詢流程圖
// deploymentId 來自 jbpm4_deployment表 DBID
// ResourceName 來自 jbpm4_lob 表 NAME
InputStream in = repositoryService.getResourceAsStream("1", "holiday/holiday.png");
OutputStream out = new FileOutputStream("c:/test.png");
int b ;
while((b=in.read())!=-1){
out.write(b);
}
in.close();
out.close();
流程定義的刪除 :
把流程 徹底從JBPM 框架中刪除了
RepositoryService 提供兩個方法 用來刪除 流程定義
可以通過流程定義釋出id刪除流程定義
方式一:如果有關聯流程例項資訊則報錯
repositoryService.deleteDeployment(deploymentId);
方式二:刪除流程定義,並刪除關聯流程例項
repositoryService.deleteDeploymentCascade(deploymentId);
Cascade 級聯的含義, 刪除流程定義時,管理流程例項資訊 也會被一起刪除,執行刪除後,關聯 lob表和 prop表資料也都刪除了, 關聯流程例項資訊也會被刪除
可以通過流程定義的key來刪除
如果沒有指定key屬性,那麼流程的名稱就是key
// 先根據key 進行查詢,在執行刪除
ProcessDefinitionQuery processDefinitionQuery =
repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> list =
processDefinitionQuery.processDefinitionKey("holiday").list();
for (ProcessDefinition processDefinition : list) {
repositoryService.deleteDeploymentCascade(processDefinition.getDeploymentId());
}
流程定義沒有修改功能,可以釋出一個新流程,版本自動+1
程式碼示例:
package com.my.jbpm;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.ZipInputStream;
import org.jbpm.api.Configuration;
import org.jbpm.api.NewDeployment;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
import org.junit.Test;
public class JBPMTest2 {
@Test
//部署 流程定義檔案
public void deploy1(){
// 1、 先獲得流程引擎 (JBPM程式設計核心)
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、通過引擎獲得需要Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、釋出流程定義
NewDeployment deployment = repositoryService.createDeployment();
deployment.addResourceFromClasspath("holiday.jpdl.xml");
deployment.addResourceFromClasspath("holiday.png");
deployment.deploy();
}
@Test
// 部署流程定義檔案 (zip格式,內含資料夾)
public void deploy2() throws FileNotFoundException{
// 1、 先獲得流程引擎 (JBPM程式設計核心)
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、通過引擎獲得需要Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、釋出流程定義
NewDeployment deployment = repositoryService.createDeployment();
deployment.addResourcesFromZipInputStream(new ZipInputStream(new FileInputStream("holiday.zip")));
deployment.deploy();
}
@Test
// 流程定義查詢
public void query(){
// 1、流程引擎
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、獲得對應的Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、 查詢流程定義
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> list = processDefinitionQuery.orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION).page(0, 2).list(); // 查詢所有流程定義
for (ProcessDefinition processDefinition : list) {
System.out.println(processDefinition.getId()); // 列印id
}
}
@Test
// 查詢流程定義圖
public void queryPng() throws IOException{
// 1、流程引擎
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、獲得對應的Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3. 查詢流程圖
// deploymentId 來自 jbpm4_deployment表 DBID
// ResourceName 來自 jbpm4_lob 表 NAME
InputStream in = repositoryService.getResourceAsStream("1", "holiday/holiday.png");
OutputStream out = new FileOutputStream("c:/test.png");
int b ;
while((b=in.read())!=-1){
out.write(b);
}
in.close();
out.close();
}
@Test
// 刪除流程定義
public void delete(){
// 1、流程引擎
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、獲得對應的Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、執行刪除
// deploymentId 是 jbpm4_deployment 的 DBID
repositoryService.deleteDeploymentCascade("10001");
}
@Test
// 刪除所有key 為 holiday 的流程
public void deleteByKey(){
// 1、流程引擎
Configuration configuration = new Configuration();
ProcessEngine processEngine = configuration.buildProcessEngine();//新建一個引擎
// 2、獲得對應的Service
RepositoryService repositoryService = processEngine.getRepositoryService();
// 3、先根據key 進行查詢,在執行刪除
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey("holiday").list();
for (ProcessDefinition processDefinition : list) {
repositoryService.deleteDeploymentCascade(processDefinition.getDeploymentId());
}
}
}
流程例項操作: 通過ExecutionService對流程例項進行操作
啟動流程例項 :
通過例項pdid啟動
executionService.startProcessInstanceById(“holiday-1”);
通過例項pdkey啟動(預設啟動相同key最新例項)
executionService.startProcessInstanceByKey(“holiday”);
如果多個流程具有相同key,會啟動版本最高的那個流程
啟動流程例項,影響的資料表:
jbpm4_execution 正在執行流程例項資訊表,ExecutionId例項ID,ID_: holiday.10001
jbpm4_hist_procinst 流程例項歷史記錄表
啟動例項,流轉到任務節點 jbpm4_task 正在執行任務資料表
jbpm4_hist_task 任務歷史記錄表
jbpm4_hist_actinst 活動的歷史記錄表
流程例項流轉操作:
通過 ExecutionService 提供 signalExecutionById (ExecutionId )
根據流程例項id 進行流轉
直接中止流程
processEngine.getExecutionService().endProcessInstance(ExecutionId, ProcessInstance.STATE_ENDED);
程式碼示例:
package com.my.jbpm;
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.junit.Test;
public class JBPMTest3 {
@Test
// 啟動一個流程 例項
public void demo1(){
// 有一個人 要執行請假流程
// 1、流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得對應的Service物件
ExecutionService executionService = processEngine.getExecutionService();
// 3、啟動具體流程
// 根據 pdId 啟動
// executionService.startProcessInstanceById("holiday-1");
// 根據key啟動
executionService.startProcessInstanceByKey("holiday");
}
@Test
// 流程例項 向後流轉
public void demo2(){
// 1、流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得對應的Service物件
ExecutionService executionService = processEngine.getExecutionService();
// 3、向後流轉
// ExecutionId 流程例項id 在 jbpm4_execution 表 ID_ 欄位
// 在向後流轉時,"to 部門經理審批" 是 transition的 name 屬性
executionService.signalExecutionById("holiday.10001","to 員工請假申請");
}
@Test
// 流程例項 流轉 (直接中止)
public void demo3(){
// 1、流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得對應的Service物件
ExecutionService executionService = processEngine.getExecutionService();
// 3、中止流程
executionService.endProcessInstance("holiday.10001", ProcessInstance.STATE_ENDED);
}
}
任務操作 :TaskService 進行任務節點操作
在實際開發中, 任務節點,通常不使用流程例項流轉功能 signalExecutionById
任務辦理,都是通過 特定使用者,以form表單提交方式進行的,任務辦理後,流轉自動流轉
在流程圖上面,為每個任務,指定任務的負責人 ,assignee屬性用來指定 個人任務
新增負責人後的holiday.jpdl.xml
<?xml version="1.0" encoding="UTF-8"?>
<process name="holiday" xmlns="http://jbpm.org/4.4/jpdl">
<start g="369,43,48,48" name="start1">
<transition g="-93,-22" name="to 員工請假申請" to="員工請假申請"/>
</start>
<task g="358,168,92,52" name="員工請假申請" assignee="員工">
<transition g="-93,-22" name="to 部門經理審批" to="部門經理審批"/>
</task>
<end g="378,384,48,48" name="end1"/>
<task g="364,281,92,52" name="部門經理審批" assignee="部門經理">
<transition g="-50,-22" name="to end1" to="end1"/>
</task>
</process>
檢視流程執行到哪個任務節點
// 查詢 當前流程例項的任務
TaskQuery taskQuery = taskService.createTaskQuery();// 任務查詢
List<Task> list = taskQuery.executionId("holiday.10001").list(); // 根據流程例項id 查詢
for (Task task : list) {
System.out.println(task.getName());
}
檢視個人任務
taskService.createTaskQuery().assignee(“張三”).list(); // 用於負責查詢
taskService.findPersonalTasks(“張三”);
// 查詢個人任務
List<Task> list = taskService.findPersonalTasks("員工"); // userId 就是 assignee 值
for (Task task : list) {
System.out.println("任務編號:" + task.getId() +", 任務名稱:" + task.getName());
}
任務編號,就是 jbpm4_task 表 DBID
個人任務辦理:TaskService提供completeTask(taskId)完成指定的任務
taskService.completeTask(“20001”);
辦理任務後,流程自動向後流轉
Task節點通常需要特定人蔘與完成,使用 completeTask
signalExecutionById 主要用於自動流轉活動節點(不需要人工干預 )
程式碼示例:
package com.my.jbpm;
import java.util.List;
import org.jbpm.api.Configuration;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.TaskQuery;
import org.jbpm.api.TaskService;
import org.jbpm.api.task.Task;
import org.junit.Test;
public class JbpmTest4 {
@Test
// 查詢流程例項的當前任務
public void demo1(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、 獲得對應Service
TaskService taskService = processEngine.getTaskService();
// 3、查詢 當前流程例項的任務
TaskQuery taskQuery = taskService.createTaskQuery();// 任務查詢
List<Task> list = taskQuery.executionId("holiday.10001").list(); // 根據流程例項id 查詢
for (Task task : list) {
System.out.println(task.getName());
}
}
@Test
// 查詢個人任務
public void demo2(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、 獲得對應Service
TaskService taskService = processEngine.getTaskService();
// 3、查詢個人任務
List<Task> list = taskService.findPersonalTasks("部門經理"); // userId 就是 assignee 值
for (Task task : list) {
System.out.println("任務編號:" + task.getId() +", 任務名稱:" + task.getName());
}
}
@Test
// 辦理個人任務
public void demo3(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、 獲得對應Service
TaskService taskService = processEngine.getTaskService();
// 3、辦理個人任務
// taskId 是 jbpm4_task 表 DBID
taskService.completeTask("20001");
}
}
流程變數操作 :
JBPM支援的流程變數型別
java.lang.String
java.lang.Long
java.lang.Double
java.util.Date
java.lang.Boolean
java.lang.Character
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Float
byte[] (byte array)
char[] (char array)
hibernate entity with a long id
hibernate entity with a string id
serializable
流程例項變數的讀寫:
變數是和流程例項相關的資料,操作流程變數,通常使用 ExecutionService 和 TaskService 兩個物件
在流程例項啟動時,通過ExecutionService 儲存流程變數
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("test", "Hello JBPM");
executionService.startProcessInstanceByKey("holiday",variables);
在執行後,流程例項變數 儲存 jbpm4_variable 表中
ExecutionService 結合 ExecutionId 進行流程變數 讀寫
// 讀取
String company =
(String) executionService.getVariable("holiday.30001", "test");
// 寫入
executionService.setVariable("holiday.30001", "weather", "陰天");
TaskService 結合 taskId 進行流程變數 讀寫
// 讀取
String weather = (String) taskService.getVariable("30003", "weather");
// 寫入
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("年齡", 20);
taskService.setVariables("30003", variables);
向流程例項中,儲存複雜物件
做法一 : 將物件實現Serializable 介面
變數資訊 jbpm4_variable 表中,Class:blob, converter:ser-bytes 說明物件 是 序列化儲存
資料儲存 jbpm4_lob 表中
做法二 : 將物件配置成Hibernate PO物件
long型別或者String 型別主鍵
Class: hld-long 是hibernate的long型別主鍵實體物件
ClassName: com.my.jbpm.Product 完整類名
Long-value : 1 是PO物件id
程式碼示例:
User.java
package com.my.jbpm;
import java.io.Serializable;
//將User物件 儲存流程例項中(序列化)
public class User implements Serializable{
private Integer id ;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Product.java
package com.my.jbpm;
//儲存流程變數 (配置 PO物件)
public class Product {
private Long id ;
private String name;
private Double price ;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
Product.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.my.jbpm.Product" table="product">
<id name="id">
<generator class="identity"></generator>
</id>
<property name="name"></property>
<property name="price"></property>
</class>
</hibernate-mapping>
JBPMTest5.java
package com.my.jbpm;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.TaskService;
import org.junit.Test;
public class JBPMTest5 {
@Test
public void demo1(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得Service
ExecutionService executionService = processEngine.getExecutionService();
// 3、啟動流程例項
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("company", "傳智播客");
executionService.startProcessInstanceByKey("holiday",variables);
}
@Test
public void demo2(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得Service
ExecutionService executionService = processEngine.getExecutionService();
// 3、讀寫流程變數
// 讀取
String company = (String) executionService.getVariable("holiday.30001", "company");
System.out.println(company);
// 寫入
executionService.setVariable("holiday.30001", "weather", "陰天");
}
// 案例三 : 使用TaskService 結合 taskId 讀寫流程變數
@Test
public void demo3(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得Service
TaskService taskService = processEngine.getTaskService();
// 3、讀寫流程變數
// 讀取
String weather = (String) taskService.getVariable("30003", "weather");
System.out.println(weather);
// 寫入
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("年齡", 20);
taskService.setVariables("30003", variables);
}
@Test
// 流程例項,儲存序列化物件
public void demo4(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得Service
ExecutionService executionService = processEngine.getExecutionService();
// 3、 儲存User物件
User user = new User();
user.setId(1);
user.setName("Rose");
executionService.setVariable("holiday.30001", "user", user);
}
@Test
// 流程例項,儲存PO物件
public void demo5(){
// 1、 流程引擎
ProcessEngine processEngine = new Configuration().buildProcessEngine();
// 2、獲得Service
ExecutionService executionService = processEngine.getExecutionService();
// 3、 儲存Product物件
Product product = new Product();
product.setName("冰箱");
product.setPrice(3000d);
Session session = new org.hibernate.cfg.Configuration().configure("jbpm.hibernate.cfg.xml").buildSessionFactory().openSession();
Transaction transaction = session.beginTransaction();
session.save(product);
transaction.commit();
session.close();
// 關聯到流程變數
executionService.setVariable("holiday.30001", "product", product);
}
}