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); 
} 
} 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/12052.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论