原
2015年11月24日 20:51:21 低调的洋仔
版权声明:本文为博主原创文章,未经博主允许不得转载。
1. 什么是JBPM4.4业务流程管理框架?
JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。
相关概念:a: 从一个节点到另一个节点==>流转。b:程序预先设定的行为==>活动。
2. JBPM工作流的特点
2.1 直观描述业务流程
采用了自己定义的JPDL:业务流程被看成是UML状态图,详细定义状态图中每个部分,起始、结束每个状态以及状态之间的转换。通过流程图的方式来呈现、直观描述业务流程。如图所示:
2.2 使用Hibernate管理数据库
通过Hibernate管理数据库,JBPM就可以把数据的管理分离出去,自己专注于业务流程。
3 ProcessEngine的核心服务
RespositoryService:流程定义的服务接口:包括流程定义的部署、查询、删除等操作。
ExecutionService: 流程执行的服务接口:包括启动流程、实例推进、设置变量等操作。
ManagementService:Web管理控制台的服务接口,包括获得消息和计时器的操作。
HistoryService:历史库的服务接口:包括对流程实例、活动实例进行查询。某个流程定义中的所有的活动的平均持续 时间,某个流程定义中的某个活动实例的转移的执行次数等操作。
IdentityService:主要包括用户、组、成员关系等相关的操作
CommondService:command模式的服务接口,实际上将客户端请求全部封装在一个调用接口中,execute(Command cmd),由这个接口去调用command接口的众多实现类。
4 怎么用JBMP?
4.1 所需环境与相关资源
1. jBPM requires a JDK (standard java) version 5 orhigher.
http://java.sun.com/javase/downloads/index.jsp
2. jBPM下载地址:http://sourceforge.net/projects/jbpm/files/
3. Eclipse下载地址( Eclipse IDE for Java EE Developers (163 MB),Version: 3.5):http://www.eclipse.org/downloads/download.php? file=/technology/epp/downloads/release/galileo
4.2 安装说明
第一步:
Help -->Install New Software...
ClickAdd...
In dialogAdd Site dialog, clickArchive...
Navigate toinstall/src/gpd/jbpm-gpd-site.zip and click 'Open'
ClickingOK in theAdd Site dialog will bring you back to the dialog 'Install'
Select thejPDL 4 GPD Update Site that has appeared
ClickNext... and thenFinish
Approve the license
Restart eclipse when that is asked
第二步:
流程定义文件的xsd文件的路径为:JBPM_HOME/src/jpdl-4.4.xsd。
添加到Eclipse中的方法为(jBPM4.4User Guide, 2.11.5. Adding jPDL 4 schema tothe catalog):
ClickWindow -->Preferences
SelectXML -->XML Catalog
Click 'Add...'
The 'Add XML Catalog Entry' dialog opens
Click the button with the map-icon next to location and select 'FileSystem...'
In the dialog that opens, select filejpdl-4.4.xsd in the src directoryof the jBPM installation root.
Click 'Open' and close all the dialogs
第三步:添加jar包
1. JBPM解压目录下有一个重要的jar包:jbpm.jar。
2. JBPM/lib目录下的jar很多,不要添加的jar包:servlet-api.jar、junit.jar(尤其不要添加)。
3. 所使用的数据库对应的驱动的jar包在上面lib目录当中已经有了,所以不需要添加了。
第四步: 添加配置文件
1. 配置文件包括jbpm.cfg.xml和jbpm.hibernate.cfg.xml(解压包当中都有模板,直接拷贝即可)
2. jbpm.hibernate.cfg.xml中配置的是Hibernate的配置信息,包括数据库连接的必要信息等等
-
<?xml version="1.0" encoding="UTF-8"?> -
<jbpm-configuration> -
<import resource="jbpm.default.cfg.xml" /> -
<import resource="jbpm.businesscalendar.cfg.xml" /> -
<import resource="jbpm.tx.hibernate.cfg.xml" /> -
<import resource="jbpm.jpdl.cfg.xml" /> -
<import resource="jbpm.bpmn.cfg.xml" /> -
<import resource="jbpm.identity.cfg.xml" /> -
<!-- Job executor is excluded for running the example test cases. --> -
<!-- To enable timers and messages in production use, this should be included. --> -
<!-- -
<import resource="jbpm.jobexecutor.cfg.xml" /> -
--> -
</jbpm-configuration>
jbpm.cfg.xml
-
<?xml version="1.0" encoding="utf-8"?> -
<!DOCTYPE hibernate-configuration PUBLIC -
"-//Hibernate/Hibernate Configuration DTD 3.0//EN" -
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> -
<hibernate-configuration> -
<session-factory> -
<!-- 数据库信息 --> -
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> -
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> -
<property name="hibernate.connection.url">jdbc:mysql:///jbpm4test</property> -
<property name="hibernate.connection.username">root</property> -
<property name="hibernate.connection.password">root</property> -
<!-- 其他配置 --> -
<property name="hibernate.hbm2ddl.auto">update</property> -
<!-- 导入映射文件 --> -
<mapping resource="jbpm.repository.hbm.xml" /> -
<mapping resource="jbpm.execution.hbm.xml" /> -
<mapping resource="jbpm.history.hbm.xml" /> -
<mapping resource="jbpm.task.hbm.xml" /> -
<mapping resource="jbpm.identity.hbm.xml" /> -
</session-factory> -
</hibernate-configuration>
jbpm.hibernate.cfg.xml
配置到此结束
4.3 JBPM工作流的使用
1. 创建jbpm的文件
2. 绘制工作流程图
绘制完成流程图之后,会相应的生成其xml中的代码(下面的代码便是自动生成的)
-
<?xml version="1.0" encoding="UTF-8"?> -
<process name="员工请假流程" xmlns="http://jbpm.org/4.4/jpdl"> -
<start g="77,20,48,48" name="start1"> -
<transition g="-71,-17" name="to 提交申请" to="提交申请"/> -
</start> -
<end g="77,352,48,48" name="end1"/> -
<task assignee="ww" g="55,268,92,52" name="总经理审批"> -
<transition g="-47,-17" name="to end1" to="end1"/> -
</task> -
<task assignee="ls" g="55,184,92,52" name="部门经理审批"> -
<transition g="-26,-8" name="同意" to="总经理审批"/> -
</task> -
<task assignee="#{applyInfo.applier.userName}" g="55,100,92,52" name="提交申请"> -
<transition g="-96,-16" name="to 部门经理审批" to="部门经理审批"/> -
</task> -
</process>
保存之后相应的生成png格式的对应的图片。
4.4 JBPM工作流编程实例
4.4.1 JBPM建表
Hibernate会自动的帮我们把所需要的表建好。
-
// 建表 -
@Test -
public void createSchema() { -
new org.hibernate.cfg.Configuration()// -
.configure("jbpm.hibernate.cfg.xml")// -
.buildSessionFactory(); -
}
4.4.2 创建ProcessEngine对象
processEngine对象十分的重要,他是使用JBPM各类接口的切入点。
1. 指定配置文件生成processEngine对象
-
private static ProcessEngine processEngine = new Configuration()// -
.setResource("jbpm.cfg.xml")// -
.buildProcessEngine();
2. 使用默认的配置文件生成processEngine对象
private ProcessEngine processEngine = new Configuration().buildProcessEngine();
3. 通过默认的配置文件生成单例的processEngine对象
private ProcessEngine processEngine = Configuration.getProcessEngine();
4.4.3 部署流程定义
流程定义:是这一次流程的步骤的说明,是对工作流程的静态式的说明信息。
-
<span style="white-space:pre"> </span>// 部署流程定义 -
@Test -
public void deployProcessDefinition() -
{ -
String reponseStr = processEngine.getRepositoryService()// -
.createDeployment()// -
.addResourceFromClasspath("test/test.jpdl.xml")//这里目录需要根据自己的目录确定 -
.addResourceFromClasspath("test/test.png")// -
.deploy(); -
System.out.println(reponseStr);// 10001 -
}
4.4.4 启动流程实例
流程实例:代表工作流的一次执行,是一种动态的过程。
1. 需要获得流程实例对象的时候
-
// 启动流程实例 -
// jbpm4_execution -
@Test -
public void testStartProcessInstance() throws Exception { -
ProcessInstance <strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;">processInstance
= processEngine.getExecutionService().startProcessInstanceByKey("test");System.out.println("流程实例启动成功:id=" +
processInstance <strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;">.getId() //
+ ", state=" +
processInstance
.getState() // 状态+ ", processDefinitionId=" +
processInstance
.getProcessDefinitionId()); // 所使用的流程定义的ID}
2. 通过key获取并直接启动实例
-
// 启动实例 -
@Test -
public void startProcessInstance() { -
processEngine.getExecutionService().startProcessInstanceByKey("test"); -
}
4.4.5 查看个人的任务列表
通过findPersonalTasks("person")可以获得具体的个人的任务列表
-
// 查询任务列表 -
@Test -
public void findTaskList() { -
List<Task> taskList = processEngine.getTaskService().findPersonalTasks("员工"); -
System.out.println("个人任务列表"); -
System.out.println(taskList); -
for(Task task : taskList) -
{ -
System.out.println("id= " + task.getId() + ", name = " + task.getName() + ", assignee = " + task.getAssignee()); -
} -
}
4.4.6 查询所有的流程定义
-
// 查询所有 -
@Test -
public void findAll() throws Exception { -
// 查询 -
List<ProcessDefinition> list = processEngine.getRepositoryService()// -
.createProcessDefinitionQuery()// -
// 过滤条件 -
// .processDefinitionKey("")// -
// .processDefinitionNameLike("%xx%")// -
// 排序条件 -
// .orderAsc(ProcessDefinitionQuery.PROPERTY_KEY)// -
// .orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION)// -
// 执行查询 -
// .uniqueResult(); -
// .count(); -
// .page(firstResult, maxResults)// -
.list(); -
// 显示 -
for (ProcessDefinition pd : list) { -
System.out.println("id=" + pd.getId()// 格式为:{key}-{version},用于唯一的标识一个流程定义 -
+ ", name=" + pd.getName()// 流程定义的名称,jpdl.xml中根元素的name属性的值 -
+ ", key=" + pd.getKey()// 流程定义的key,jpdl.xml中根元素的key属性的值,默认是name属性的值 -
+ ", version=" + pd.getVersion()// 自动生成的,同一个名称的第一个为1,以后的自动加1. -
+ ", deploymentId=" + pd.getDeploymentId()); // 所属的部署对象 -
} -
}
4.4.7 查询最新版的流程定义
-
// 查询所有最新版本的流程定义 -
@Test -
public void findAllLatestVersions() throws Exception { -
// 查询所有,让所有最大的版本都排到最后面 -
List<ProcessDefinition> all = processEngine.getRepositoryService()// -
.createProcessDefinitionQuery()// -
.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION)// -
.list(); -
// 过滤出所有最新的版本 -
Map<String, ProcessDefinition> map = new HashMap<String, ProcessDefinition>(); -
for (ProcessDefinition pd : all) { -
map.put(pd.getKey(), pd); -
} -
// 显示 -
for (ProcessDefinition pd : map.values()) { -
System.out.println("id=" + pd.getId()// 格式为:{key}-{version},用于唯一的标识一个流程定义 -
+ ", name=" + pd.getName()// 流程定义的名称,jpdl.xml中根元素的name属性的值 -
+ ", key=" + pd.getKey()// 流程定义的key,jpdl.xml中根元素的key属性的值,默认是name属性的值 -
+ ", version=" + pd.getVersion()// 自动生成的,同一个名称的第一个为1,以后的自动加1. -
+ ", deploymentId=" + pd.getDeploymentId()); // 所属的部署对象 -
} -
}
4.4.8 删除流程定义
-
// 删除 -
@Test -
public void deleteById() throws Exception { -
String deploymentId = "80001"; -
// // 删除指定的部署对象(流程定义),如果有关联的执行信息,就会报错 -
// processEngine.getRepositoryService().deleteDeployment(deploymentId); -
// 删除指定的部署对象(流程定义),如果有关联的执行信息,会被同时删除 -
processEngine.getRepositoryService().deleteDeploymentCascade(deploymentId); -
}
-
// 删除指定key的所有版本的流程定义 -
@Test -
public void deleteByKey() throws Exception { -
// 查询出指定key的所有版本的流程定义 -
List<ProcessDefinition> list = processEngine.getRepositoryService()// -
.createProcessDefinitionQuery()// -
.processDefinitionKey("helloworld")// -
.list(); -
// 一一删除 -
for (ProcessDefinition pd : list) { -
processEngine.getRepositoryService().deleteDeploymentCascade(pd.getDeploymentId()); -
} -
}
4.4.9 查看流程图
-
// 查看流程图(xxx.png) -
@Test -
public void getImageResource() throws Exception { -
String deploymentId = "50001"; -
String resourceName = "helloworld/helloworld.png"; -
// 获取指定部署对象中的所有资源的名称 -
Set<String> names = processEngine.getRepositoryService().getResourceNames(deploymentId); -
System.out.println("所有的资源名称:"); -
for (String name : names) { -
System.out.println("\t" + name); -
} -
// 获取指定部署对象中的指下资源的内容 -
InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, resourceName); -
// 保存到c盘 -
OutputStream out = new FileOutputStream("c:/process.png"); -
for (int b = -1; (b = in.read()) != -1;) { -
out.write(b); -
} -
in.close(); -
out.close(); -
}
4.4.10 向后执行一步
-
// 向后执行一步 -
@Test -
public void testSignalExecution() throws Exception { -
String executionId = "test.130001"; -
processEngine.getExecutionService().signalExecutionById(executionId); -
// processEngine.getExecutionService().signalExecutionById(executionId, parametersMap); // 离开前先设置一些流程变量 -
// processEngine.getExecutionService().signalExecutionById(executionId, signalName); // 使用指定名称的Transition离开本活动 -
// processEngine.getExecutionService().signalExecutionById(executionId, signalName, parameters) // 离开前先设置一些流程变量,再使用指定名称的Transition离开本活动 -
}
4.4.11 办理任务
-
// 办理任务 -
@Test -
public void testCompleteTask() throws Exception { -
String taskId = "130002"; -
processEngine.getTaskService().completeTask(taskId); -
}
4.4.12 设置流程变量
-
// 设置流程变量 -
@Test -
public void testSetVariable() throws Exception { -
String executionId = "test.150001"; -
processEngine.getExecutionService().setVariable(executionId, "请假天数", 15); -
}
-
// 获取流程变量 -
@Test -
public void testGetVariable() throws Exception { -
String executionId = "test.150001"; -
Integer days = (Integer) processEngine.getExecutionService().getVariable(executionId, "请假天数"); -
System.out.println("请假天数 = " + days); -
}
-
{ -
ExecutionService executionService = processEngine.getExecutionService(); -
TaskService taskService = processEngine.getTaskService(); -
// ============ 设置变量 ======================== -
executionService.setVariable(executionId, name, value); // 设置一个变量 -
executionService.setVariables(executionId, variablesMap); // 设置多个变量 -
taskService.setVariables(taskId, variables); // 设置多个变量 -
executionService.startProcessInstanceByKey(processDefinitionKey, variablesMap); // 启动流程实例时,先设置一些变量 -
taskService.completeTask(taskId, variablesMap); // 真正办理完任务前先设置一些变量 -
// ============ 获取变量 ======================== -
executionService.getVariable(executionId, variableName); // 获取一个变量 -
executionService.getVariableNames(executionId); // 返回Set<String>,是所有变量的名称集合 -
executionService.getVariables(executionId, variableNames); //获取多个变量,返回Map<String,Object>,表示指定名称的变量信息 -
taskService.getVariable(taskId, variableName); -
taskService.getVariableNames(taskId); -
taskService.getVariables(taskId, variableNames); -
}
4.4.13 流程执行
-
@Test -
public void testProcess() throws Exception { -
// 部署流程定义 -
InputStream in = this.getClass().getResourceAsStream("test.jpdl.xml"); -
String deploymentId = processEngine.getRepositoryService()// -
.createDeployment()// -
.addResourceFromInputStream("test.jpdl.xml", in)// -
.deploy(); -
System.out.println("部署流程定义完毕:deploymentId = " + deploymentId); -
// 启动流程实例 -
ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey("test"); -
System.out.println("流程实例启动完毕:processInstanceId = " + pi.getId()); -
// 完成第一步“提交申请”的任务,要使用指定的Transition离开当前活动 -
Task task = processEngine.getTaskService()// -
.createTaskQuery()// 获取本流程实例中当前情况下仅有的一个任务 -
.processInstanceId(pi.getId())// -
.uniqueResult(); -
String transitionName1 = "to 部门经理审批"; -
String transitionName2 = "to 总经理审批"; -
processEngine.getTaskService().completeTask(task.getId(), transitionName2); // 使用指定名称的Transition离开本活动 -
}
4.4.14 分配任务
-
public class AssignmentHandlerImpl implements AssignmentHandler { -
// 计算此任务的办理人,并分配任务 -
@Override -
public void assign(Assignable assignable, OpenExecution execution) throws Exception { -
System.out.println("---> AssignmentHandlerImpl.assign()"); -
// 计算办理人 -
String userId = "李经理--"; -
// 分配个人任务 -
assignable.setAssignee(userId); // 指定个人任务的办理人 -
// // 分配组任务 -
// assignable.addCandidateUser("小A"); // 添加一个候选人(组任务) -
// assignable.addCandidateUser("小B"); // 添加一个候选人(组任务) -
// assignable.addCandidateUser("小C"); // 添加一个候选人(组任务) -
} -
}
4.4.15 组任务与分配
-
public class ProcessTest { -
private static ProcessEngine processEngine = Configuration.getProcessEngine(); -
@Test -
public void testProcess() throws Exception { -
// 部署流程定义 -
InputStream in = this.getClass().getResourceAsStream("test.jpdl.xml"); -
String deploymentId = processEngine.getRepositoryService()// -
.createDeployment()// -
.addResourceFromInputStream("test.jpdl.xml", in)// -
.deploy(); -
System.out.println("部署流程定义完毕:deploymentId = " + deploymentId); -
// 启动流程实例 -
Map<String, Object> variables = new HashMap<String, Object>(); -
variables.put("manager", "王经理"); -
variables.put("userIds", "小A,小B,小C,小D"); -
ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey("test", variables); -
System.out.println("流程实例启动完毕:processInstanceId = " + pi.getId()); -
} -
// 查询组任务列表 -
@Test -
public void testFindMyGroupTaskList() throws Exception { -
String userId = "王工程师"; -
// String userId = "赵工程师"; -
// 查询 -
// List<Task> list = processEngine.getTaskService().findGroupTasks(userId); -
// 分页 -
List<Task> list = processEngine.getTaskService()// -
.createTaskQuery()// -
.candidate(userId)// 指定候选人,这是查询组任务 -
.page(0, 100)// 分页 -
.list(); -
// 显示 -
System.out.println("====== " + userId + "的个人任务列表 ======"); -
for (Task task : list) { -
System.out.println("id=" + task.getId()// -
+ ", name=" + task.getName()// -
+ ", assignee=" + task.getAssignee()// -
+ ", createTime=" + task.getCreateTime()// -
+ ", executionId=" + task.getExecutionId()); -
} -
} -
// 拾取任务 -
@Test -
public void testTakeTask() throws Exception { -
String taskId = "310009"; -
String userId = "王工程师"; -
processEngine.getTaskService().takeTask(taskId, userId); -
} -
// 查询个人任务列表 -
@Test -
public void testFindMyPersonalTaskList() throws Exception { -
String userId = "王工程师"; -
// 查询 -
// List<Task> list = processEngine.getTaskService().findPersonalTasks(userId); -
// 分页 -
List<Task> list = processEngine.getTaskService()// -
.createTaskQuery()// -
.assignee(userId)// 指定办理人条件 -
.page(0, 100)// 分页 -
.list(); -
// 显示 -
System.out.println("====== " + userId + "的个人任务列表 ======"); -
for (Task task : list) { -
System.out.println("id=" + task.getId()// -
+ ", name=" + task.getName()// -
+ ", assignee=" + task.getAssignee()// -
+ ", createTime=" + task.getCreateTime()// -
+ ", executionId=" + task.getExecutionId()); -
} -
} -
// 直接指定任务的办理人 -
@Test -
public void testAssignTask() throws Exception { -
String taskId = "310009"; -
// String userId = null; // 退回到组任务列表 -
String userId = "赵工程师"; -
processEngine.getTaskService().assignTask(taskId, userId); -
} -
}