初次接触工作流是在OA中,现在再为简略的总结一下,这篇文章要说的是JBPM宏观结构、简单实例、扩展使用三部分。
JBPM
Java Business Process Management,覆盖了业务流程管理、工作流、服务协作等领域,并且是一个开源的、灵活的、易扩展的流程语言框架。
简单的说,JBPM是一个框架,结合hibernate、数据库、流程图、描述语言等,专门处理与工作流有关的问题。
JPDL
JBoss jBPM Process Definition Language,用于构建jBPM的流程语言,既然是语言,必然要有控制结构、语法、变量等概念,它把一个工作流看作是UML状态图,jPdl的作用就是定义状态图的每个部分,如起始、结束状态。
它的语言的作用可以是通过拖拽组件或编辑XML文件的方式实现,如通过流程传递,实现顺序结构,详见以下实例。
核心内容
以一张图的方式展示JBPM的核心内容,如下:
如上所示,JBPM按照既定的流程图,通过封装的8个核心对象,以Hibernate的方式操作数据库,将各个流程的操作持久化,保存到数据库中。
如有兴趣,可以按照流程的传递,去跟踪流程和任务在数据中转移的顺序,加深对JBPM的了解。
简单使用
语言定义
<?xml version="1.0" encoding="UTF-8"?>
<process key="test" name="test1" xmlns="http://jbpm.org/4.4/jpdl">
<start g="284,14,48,48" name="start1">
<transition g="-52,-22" name="提交给一级主管" to="一级主管审批"/>
</start>
<task assignee="A" g="262,107,92,52" name="一级主管审批">
<transition g="-68,-8" name="提交到二级主管" to="二级主管审批"/>
</task>
<task assignee="B" g="263,193,92,52" name="二级主管审批">
<transition g="-37,-11" name="通过" to="end1"/>
</task>
<end g="286,281,48,48" name="end1"/>
</process>
流程图片
ServiceFactory
用于创建各个对象。
package com.tgb.jbpm;
import junit.framework.TestCase;
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskService;
public class ServiceFactory extends TestCase {
private ProcessEngine processEngine;
private RepositoryService repositoryService;
private ExecutionService executionService;
private TaskService taskService;
/***
* 得到各个服务对象
*/
protected void startUp(){
processEngine=Configuration.getProcessEngine();
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
taskService=processEngine.getTaskService();
}
//此处省略getter和setter
}
TestFlow
测试各个流程步骤所产生的结果。
package com.tgb.jbpm;
import java.util.List;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.task.Task;
public class TestFlow extends ServiceFactory {
protected String instanceId;
protected String taskId;
/***
* 按步骤的流程
*/
public void flow(){
//初始化服务
startUp();
//部署工作流
deploy();
//创建工作流实例
createInstanceByKey();
//查询A下的任务
getTasksByPersonId();
//结束任务“一级主管审批”
completeTaskById();
//查询工作流实例所在的任务实例
getCurrentTaskByInstanceId();
}
/***
* 部署工作流
*/
public void deploy(){
getRepositoryService().createDeployment()
.addResourceFromClasspath("test1.jpdl.xml").deploy();
System.out.println("工作流已经成功部署!");
}
/***
* 创建流程实例,保存实例Id
*/
public void createInstanceByKey()
{
ProcessInstance processInstance=getExecutionService()
.startProcessInstanceByKey("test");
instanceId=processInstance.getId();
System.out.println("已成功创建新实例,Id为:"+processInstance.getId());
}
/****
* 得到任务实例信息
*/
public void getTasksByPersonId(){
List<Task> task=getTaskService().findPersonalTasks("A");
taskId=task.get(0).getId();
System.out.println("任务数量:"+task.size());
System.out.println("任务名称:"+task.get(0).getName());
System.out.println("任务人员:"+task.get(0).getAssignee());
System.out.println("任务ID:"+task.get(0).getId());
}
/***
* 查询实例所在任务节点
*/
public void getCurrentTaskByInstanceId(){
startUp();
String activity=getExecutionService().createProcessInstanceQuery()
.processInstanceId(instanceId)
.uniqueResult().toString();
System.out.println("当前所在结点为:"+activity);
}
/***
* 根据流程实例id结束任务
*/
public void completeTaskById(){
startUp();
getTaskService().completeTask(taskId);
}
}
运行结果
工作流已经成功部署!
已成功创建新实例,Id为:test.20007
任务数量:2
任务名称:一级主管审批
任务人员:A
任务ID:10002
当前所在结点为:execution[test.20007]
以上是最简单的顺序结构,你可以使用更复杂的结构,如:
仔细看会发现,上述的代码写的很"死",不只是代码,工作流的定义文件中,流程"A"和"B"等也定义的很“死”,难道JBPM以如此不灵活的方式应对复杂的工作流程?当然不是,这也是下面要说的内容。
扩展使用
文章篇幅有限,不再把JBPM的每种使用和注意事项都写一遍,但会提供以下思路:
- JBPM支持为流程实例和任务实例添加参数,这些参数可以保存到数据库中
- 部件如task含有form等内置属性,结合struts,可以更灵活的控制跳转
- JBPM保存了历史数据,可以结合这些历史扩展程序的功能
- 和EL表达式结合变量和对象使用,更灵活,如<task assignee="${admin.user}" g="262,107,92,52" name="一级主管审批">
总结
以上即是对JBPM大面上的总结,实例也可满足简单的使用,更多细节问题,有待在实战中发现。