JBPM
JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。jBPM是公开源代码项目,使用它要遵循 ASL(Apache License Version 2.0)和EULA(JBoss End User License Agreement)协议。
JBPM的运行需要数据库的支持,因此系统设计时要选定所用数据库。
这里使用Oracle作为数据库。使用JBPM的版本是 jbpm-jpdl-3.2.3。
一、建表空间,建用户
--创建表空间
CREATE TABLESPACE jbpm
DATAFILE 'E:\orcl_tblspace\jbpm.DBF'
SIZE 10M
AUTOEXTEND ON NEXT 32M MAXSIZE UNLIMITED
LOGGING
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO; //以分号结束
--创建用户
CREATE USER jbpm
IDENTIFIED BY jbpm
DEFAULT TABLESPACE jbpm;
--把CONNECT、RESOURCE角色授予用户jbpm
GRANT CONNECT,RESOURCE TO jbpm
三、导入JBPM的表,在jbpm-jpdl-3.2.3/db下找到jbpm.jpdl.oracle,把他导入到新建的数据库用户中,先把该sql文件中的 drop table JBPM_ACTION cascade constraints; 之类语句先删掉。接着,数据库中会多了32张表。
二、建JavaWeb Project
1.在jbpm-jpdl-3.2.3/config中把如下4个文件复制到新建的JavaWeb Project中的src目录下。
a.hibernate.cfg
b.jbpm.cfg
c.jbpm.mail.templates
d.log4j.properties
2.把jbpm-jpdl-3.2.3/lib中的jar文件做成一个自定义的类库,然后导入到Java Project中。
3.导入Oracle的数据库驱动包。
4.修改hibernate.cfg配置文件中的dialect、driver_class、url、username和password。
5.顺便导入JUnit 4的类库,待会用作测试。
6.在JavaWeb Project中新建一工作流文件夹,例如workflow,用来存放流程图。
三、新建工作流文件(流程开始时带任务人)
PS:gpd.xml文件可能会报错,不用管,编码问题而已,也不需要打开查看。
4.打开processdefinition.xml文件。开始画流程图
5.流程图的一些解释。
6.员工申请报销 流程的设置
Description那里写的是 staff.apply
Assignment是指分派任务,Actor有可以指定作用域或者直接指定人名,例如Jack。
7.部门经理审批 的流程设置
Description那里写的是 manager.approve
这次的分配任务交给一个Java类来处理,选择Handler,这个类要实现AssignmentHandler这个接口。
8.财务审批 流程的设置
9.通知员工 的流程设置
这里的Actor所指定的角色必须要和 员工申请报销 流程里的Actor所指定的角色一样。
10.当设置好流程图的属性的时候,就可以开始部署了。
接着,点击Save Without Deploying... 这个按钮,你就发现你所选择的目录里会多了一个.zip压缩包。
11.此时,需要一个Java类,把流程图的属性写入到数据库中
package org.jbpm.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipInputStream;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
/**
* 部署类
*
* @author miao
*
*/
public class DelpoymentUtil {
/**
* @param args
*/
public static void main(String[] args) {
// 上下文
JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
// 该目录是画完流程图之后的部署位置
String url = "C:\\Homework\\JaveSpace\\workStream\\leave.zip";
try {
// 输入流
InputStream is = new FileInputStream(new File(url));
// ZipInputStream是InputStream的子类,通过此类可以方便地读取ZIP格式的压缩文件
ZipInputStream zis = new ZipInputStream(is);
// 流程定义类
ProcessDefinition pd = ProcessDefinition.parseParZipInputStream(zis);
jbpmContext.deployProcessDefinition(pd);
zis.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
}
运行这个类之后,会在数据库里的 JBPM_TASK 表和 JBPM_TASKINSTANCE 表发现数据。
四、编码
做个简单的申请报销处理类
package org.jbpm.process;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.def.AssignmentHandler;
import org.jbpm.taskmgmt.exe.Assignable;
/**
* 报销类
*
* @author miao
*
*/
public class ApplyProcess implements AssignmentHandler {
public void assign(Assignable assignable, ExecutionContext context) throws Exception {
// 该名字就是流程图里员工申请报销的那位,通过上下文获取
String name = context.getContextInstance().getVariable("issueperson").toString();
if ("user1".equals(name)) {
assignable.setActorId("manager1");
} else if ("user2".equals(name)) {
assignable.setActorId("manager2");
}
}
}
五、测试类
package org.jbpm.test;
import java.util.List;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.context.exe.ContextInstance;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* 测试员工报销
*
* @author miao
*
*/
public class TestApplyMoney {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@Test
public void testProcess() {
// 1.员工提交申请
submitForm("user1");
// 2.部门经理审核
//managerApprove("manager1");
// 3.财务拨款
//cashierApprove("ali");
// 4.员工领款
//getMoney("user1");
}
/**
* 1.添加员工提交申请
*
* @param actorId
*/
public void submitForm(String actorId) {
JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
try {
ProcessDefinition pd = jbpmContext.getGraphSession().findLatestProcessDefinition(
"applyMoney");
ProcessInstance pi = pd.createProcessInstance();
ContextInstance ci = pi.getContextInstance();
jbpmContext.setActorId(actorId);
ci.setVariable("issueperson", actorId);
TaskInstance ti = pi.getTaskMgmtInstance().createStartTaskInstance();
ti.end();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
/**
* 2.部门经理审批
*
* @param actorId
*/
public void managerApprove(String actorId) {
JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
try {
@SuppressWarnings("unchecked")
List list = jbpmContext.getTaskList(actorId);
for (TaskInstance taskInstance : list) {
taskInstance.end();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
/**
* 3.财务拨款
*
* @param actorId
*/
public void cashierApprove(String actorId) {
JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
try {
@SuppressWarnings("unchecked")
List list = jbpmContext.getTaskList(actorId);
for (TaskInstance taskInstance : list) {
taskInstance.end();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
/**
* 4.员工领款
*
* @param actorId
*/
public void getMoney(String actorId) {
JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
try {
@SuppressWarnings("unchecked")
List list = jbpmContext.getTaskList(actorId);
for (TaskInstance taskInstance : list) {
taskInstance.end();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
}
每测试一个方法,就会在数据库中的 JBPM_TASKINSTANCE 表看见相应的数据。
六、demo(该例子中也包含复杂一点的流程处理,带分支判断,流程开始时不带任务人)
E276-JBPM.zip