JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。
相关概念:a: 从一个节点到另一个节点==>流转。b:程序预先设定的行为==>活动。
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
1. JBPM解压目录下有一个重要的jar包:jbpm.jar。
2. JBPM/lib目录下的jar很多,不要添加的jar包:servlet-api.jar、junit.jar(尤其不要添加)。
3. 所使用的数据库对应的驱动的jar包在上面lib目录当中已经有了,所以不需要添加了。
<?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
<?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格式的对应的图片。
// 建表 @Test public void createSchema() { new org.hibernate.cfg.Configuration()// .configure("jbpm.hibernate.cfg.xml")// .buildSessionFactory(); }
private static ProcessEngine processEngine = new Configuration()// .setResource("jbpm.cfg.xml")// .buildProcessEngine();
private ProcessEngine processEngine = new Configuration().buildProcessEngine();
private ProcessEngine processEngine = Configuration.getProcessEngine();
<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 }
// 启动流程实例 // 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"); }
// 查询任务列表 @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()); } }
// 查询所有 @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()); // 所属的部署对象 } }
// 查询所有最新版本的流程定义 @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()); // 所属的部署对象 } }
// 删除 @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()); } }
// 查看流程图(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(); }
// 向后执行一步 @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离开本活动 }
// 办理任务 @Test public void testCompleteTask() throws Exception { String taskId = "130002"; processEngine.getTaskService().completeTask(taskId); }
// 设置流程变量 @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); }
@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离开本活动 }
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"); // 添加一个候选人(组任务) } }
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); } }