宅急送项目的第七天笔记!(JBPM工作流)

宅急送项目的第七天 
三个主要功能模块: 基础设置、 取派业务、中转配送业务 

基础设置: 标准管理、取派员管理、区域设置、分区设置、定区管理
取派业务: 业务受理、工作单快速录入(追单、销单)、 工作单批量导入 

一、工作流概述

面对复杂业务流程,非常大数据量 ----- 系统是如何管理流程的各个环节不会出错 
** 只由数据库 保存当前业务单 状态,无法精确操作下一环节 (非常容易出错)

利用两天时间 学习 jbpm 工作流管理框架 
**  工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化 
**  对于复杂的业务流程,通过工作流系统进行管理,实现文档、信息、任务 自动化传递 

工作流技术,广泛应用 OA 、ERP 、CRM 管理系统中 

什么是jbpm ?  工作流开源框架 
jBpm是一个灵活可扩展的工作流管理系统。作为 jBpm运行时server输入的业务流程使用简单强大的语言表达并打包在流程档案中。jBmp将工作流应用开发的便利性和杰出的企业应用集成(EAI)能力结合了起来。jBmp包括一个Web应用程序和一个日程安排程序。jBmp是一组J2SE组件,可以作为J2EE应用集群部署。

*** 企业中其它著名的工作流: OfBiz 、osWorkFlow 

使用工作流技术演示程序
1、 MyProcessDesigner_流程设计器  (awt技术实现jbpm 流程设计器 )
2、 MyJbpm4-Console_Procject-Src_2011-01-05.zip (使用jbpm 请假系统 小项目)
3、 tomcat-6.0.14 (运行了 请假流程系统的项目)

jbpm 默认采用hibernate集成 ,实现演示用例时,修改数据库连接信息 WEB/INF/classes/jbpm.hibernate.cfg.xml 
默认数据库 jbpm4console
默认用户 root
默认密码 root 

启动tomcat 必须配置JAVA_HOME 
http://localhost:8080/MyJbpm4-Console 

默认登录角色 admin (管理员)、员工(进行请假)、部门经理(批假)

jbpm 业务流程,同编写xml完成 ,在实际中使用图形设计器来完成 
* MyProcessDesigner_流程设计器 

二、 jbpm使用开发 (快速入门)
1、 下载jbpm 开发包  最新版本5.4 , 课程以4.4 为主 
doc 文档 ( 开发者手册,用户手册,javadoc ) -------------- userguide 
examples 案例
install 安装 
lib  jar包
src  源码 

jbpm.jar  核心jar包 

分为两个部分开发: 流程定义 (xml格式,通过插件画图完成)、 编码操作jbpm流程 

2、 安装myeclise jbpm开发插件 
需要 eclipse3.5 以上版本  --------- myeclipse8.5 
1 启动myeclipse10 ---- 选择help-->MyEclipse Configuration Center-->Software;
2 左边Browse Software选择add site---->Add from Archive File
3 name写jbpm4.4 , url 写 ${jbpm4.4 解压目录}/install/src/jpd/jbpm-gpd-site.zip 文件路径 ,点击OK
4 左边Browse Software下会出现Personal Sites , 下面有个jbpm4 ,将下面8个组件分别右键 add to profile
5 这时候右下角Software Updates Available会出现你要安装的插件 ,拔掉网线后点击Apply change
6 安装完成后,会提醒是否重启Myeclipse
7 重启后在你的 window - preferences 中 多了一个JBoss jBPM

3、 搭建工程环境 
导入jar包 (jbpm 默认和hibernate已经整合,整合hibernate版本3.3.1 )

JBPM4.4 + Struts2.3.7 + Spring 3.2 + Hibernate3.6 

配置文件 
src/log4j.properties 
从jbpm解压目录/examples/src 导入 jbpm.cfg.xml (JBPM核心配置文件) 、jbpm.hibernate.cfg.xml (Hibernate的配置文件 )

修改 jbpm.hibernate.cfg.xml中数据库连接参数 
<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:///jbpm01</property>
     <property name="hibernate.connection.username">root</property>
     <property name="hibernate.connection.password">abc</property>
     <property name="hibernate.hbm2ddl.auto">update</property>
     <property name="hibernate.format_sql">true</property>
     <property name="hibernate.show_sql">true</property>

4、 helloworld 案例 (请假流程)
新建jbpm 流程定义  helloworld ------ 制作为zip文件 

5、 使用jbpm api 操作业务流程
1) 使用hibernate 完成 jbpm 建表工作 
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration(); // 加载hibernate.properties
configuration.configure("jbpm.hibernate.cfg.xml"); // 默认加载hibernate.cfg.xml
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
session.close();
sessionFactory.close();
创建了18张表 
jBPM4.4的数据库表分成以下几类:
1)和系统相关:
这个只有JBPM4_PROPERTY
2)和ProcessDefinition相关的表:
有:JBPM4_DEPLOYMENT、JBPM4_DEPLOYPROP、JBPM4_LOB
3)和开启一个instance相关:
有JBPM4_EXECUTION、JBPM4_TASK、JBPM4_JOB、JBPM4_VARIABLE、JBPM4_SWIMLANE、JBPM_PARTICIPATION
4)和历史相关的表:
JBPM4_HIS_ACTINST、JBPM4_HIS_DETAIL、JBPM4_HIS_PROCINST、JBPM4_HIS_TASK、JBPM4_HIS_VAR
5)和用户/组相关的表有:
JBPM4_ID_USER、JBPM4_ID_GROUP、JBPM4_ID_MEMBERSHIP

2) 使用 jbpm完成建表 org.jbpm.api.Configuration.getProcessEngine(); 
底层代码  (new Configuration()).setResource("jbpm.cfg.xml").buildProcessEngine();

**** 获得ProcessEngine 流程引擎, 可以获得不同Service对象,来完成相应的功能

3) 部署实例 RepositoryService getRepositoryService() 
// 获得实例管理Service
RepositoryService repositoryService =  processEngine.getRepositoryService();
// 创建一个部署对象
NewDeployment createDeployment = repositoryService.createDeployment();

createDeployment.addResourceFromClasspath("helloworld/helloworld.jpdl.xml");
createDeployment.addResourceFromClasspath("helloworld/helloworld.png");
// 发布
createDeployment.deploy();

4) 启动节点 进行请假 ExecutionService getExecutionService() 
ProcessEngine processEngine = org.jbpm.api.Configuration.getProcessEngine();
// 启动流程 获得ExecutionService
ExecutionService executionService = processEngine.getExecutionService();
// 设计流程时,流程有name ---- 默认生成流程key
executionService.startProcessInstanceByKey("helloworld");

5) 查看任务 TaskService getTaskService() 
ProcessEngine processEngine = org.jbpm.api.Configuration.getProcessEngine();
// 查看任务
TaskService taskService = processEngine.getTaskService();
// 查询个人任务 
List<Task> personalTasks = taskService.findPersonalTasks("部门经理");
System.out.println(personalTasks.size());
for (Task task : personalTasks) {
System.out.println("任务id : " + task.getId());
System.out.println("任务名称: " + task.getName());
System.out.println("任务的办理人 : " + task.getAssignee());
System.out.println("执行流程实例id :" + task.getExecutionId());
System.out.println("-------------------------");
}

6) 办理任务 TaskService getTaskService() 
ProcessEngine processEngine = org.jbpm.api.Configuration.getProcessEngine();
// 查看任务
TaskService taskService = processEngine.getTaskService();
// 必须通过任务id进行办理
taskService.completeTask("10002");

====================================================================================
三、 jbpm 操作详解 ---- 流程发布(流程实例管理)
1、 创建数据表 
org.jbpm.api.Configuration.getProcessEngine(); // 获得流程引擎的过程中完成 建表 18张表 
*** 必须使用默认的配置文件 src/jbpm.cfg.xml 

如果想自定义配置文件的名称 
(new Configuration()).setResource("jbpm.cfg.xml").buildProcessEngine(); // 指定配置文件的名称

2、 建表后,绘制业务流程文件xml ----- 部署流程 Deloy 
建表过程中,向JBPM4_PROPERTY 表插入一条数据   
version:0 没有业务流程被发布,每发布一个不同业务流程,version + 1 、
value 下一个dbid的值  (dbid相当于一个流水号,jbpm所有表 公用一个流水号【不连续】 )

发布流程时,向三个表insert , 向 JBPM4_DEPLOYMENT、JBPM4_LOB、JBPM4_DEPLOYPROP 
jbmp4_deployment:流程定义的部署记录; ----- id : 1  (代表发布一个业务流)
jbmp4_lob:流程定义的相关资源,包括jPDL XML、图片、用户代码Java类等,以二进制格式统一存储在此表中; ----- id : 2 、3 (xml和png)
jbmp4_deployprop:已部署的流程定义的具体属性: ---------- 
langid 版本信息 jpdl-4.4
pdid  业务流程实例id (唯一标识)helloworld-1 (-1 版本)
pdkey  如果指定key就是指定key值,如果没有指定key 默认使用name值 
pdversion 流程实例版本  1 

两种发布 
第一种: 添加xml和png
repositoryService.createDeployment()
.addResourceFromClasspath("helloworld/helloworld.jpdl.xml") // xml流程定义文件
.addResourceFromClasspath("helloworld/helloworld.png").deploy();  // 发布流程图片
第二种: 添加zip
ZipInputStream zipinputstream = new ZipInputStream(new FileInputStream("helloworld.zip"));
repositoryService.createDeployment().addResourcesFromZipInputStream(zipinputstream).deploy();

******** 系统不允许发布两个相同name 但是 key不同流程实例  (如果name相同,key必须相同)

3、 查询所有已经发布实例 
DeploymentQuery createDeploymentQuery()  ------ jbpm4_deployment   查询发布信息
ProcessDefinitionQuery createProcessDefinitionQuery() ----- jbpm4_deployprop  查询流程实例详细属性  (重点)

查询所有
RepositoryService repositoryService = Configuration.getProcessEngine().getRepositoryService();
// 获得查询流程实例 Query对象
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
// 查询所有流程 
List<ProcessDefinition> list = processDefinitionQuery.list();
for (ProcessDefinition processDefinition : list) {
System.out.println("流程对应id :"+processDefinition.getId());
System.out.println("流程对应name: " + processDefinition.getName());
System.out.println("流程对应key : " + processDefinition.getKey());
System.out.println("版本:" + processDefinition.getVersion());
System.out.println("------------------------------");
}

查询指定的流程实例  count 个数、 orderAsc/OrderDesc 升降序  page(i,j) 分页   processDefinitionId() / name/ key /version条件

4、删除流程实例
1) 根据id 删除流程实例 ,同时删除 log表 、deloyprop表 
RepositoryService repositoryService = Configuration.getProcessEngine().getRepositoryService();
// 删除id (通过发布id删除)
repositoryService.deleteDeployment("1");

注意问题: 如果流程以及开启了(含有执行信息,将无法删除 )
解决: repositoryService.deleteDeploymentCascade(("20001");  (重点)

2) 根据key值删除 (用于同一个流程 发布了多个版本)
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("holiday").list();
for (ProcessDefinition processDefinition : list) {
repositoryService.deleteDeployment(processDefinition.getDeploymentId());// 传入发布id
}  // 根据发布id来删除 

5、 修改流程 ???  不允许 
当你新发布流程后,添加一个新的流程,默认情况下在启动流程时,将启动新流程 
*** 发布时,不会自动删除原有流程,添加了一个新版本的流程 

注意事项一: 虽然不能修改,如果根据key启动流程, 默认启动最新版本 
   **** 引发问题: 如果已经旧版本流程正在执行,发布了新版本会怎么样 ?  之前流程按照原有流程操作 
注意事项二: 查询到最新的请假流程 
RepositoryService repositoryService = Configuration.getProcessEngine().getRepositoryService();
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("holiday").orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION).list();
if(list.size() > 0){
ProcessDefinition processDefinition = list.get(0);
System.out.println("流程对应id :"+processDefinition.getId());
System.out.println("流程对应name: " + processDefinition.getName());
System.out.println("流程对应key : " + processDefinition.getKey());
System.out.println("版本:" + processDefinition.getVersion());
}

====================================================================================
四、业务流程执行过程中 数据操作 
1、 如何启用流程实例 ExecutionService 
ExecutionService executionService = Configuration.getProcessEngine().getExecutionService();
// 启动流程,使用id启动非常少 ----- 通常使用key启动 
executionService.startProcessInstanceByKey("holiday");

第一步 向 jbpm4_execution 表插入一条数据 
信息: 当前正在执行流程定义id 、流程实例id 、当前执行节点名称 

第二步 记录历史记录 jbpm4_hist_procinst (一个实例启动了 )

第三步 因为开始节点后,就是task节点,初始化任务信息, 向 jbpm4_task 插入一条数据
assignee 操作人概念 !!!!  (查询我的任务列表,我未完成的任务 )

第四步 为任务记录历史记录 jbpm4_hist_task 

第五步 向历史活动记录表 jbpm4_hist_actinst 中插入数据 

jbpm4_executon:流程实例及执行对象
jbmp4_hist_procinst:保存历史的流程实例记录
jbpm4_task:流程实例的任务记录
jbpm4_hist_task:保存历史的任务实例记录
jbpm4_hist_actinst:保存历史的活动实例记录

2、 办理任务  TaskService 
TaskService taskService = Configuration.getProcessEngine().getTaskService();
// 办理任务
taskService.completeTask("10002");// 传入任务id

第一步 : 对任务活动记录表,进行更新  jbpm4_hist_actinst
第二步 : 对任务历史表更新jbpm4_hist_task
第三步: 删除执行任务jbpm4_task (任务在执行后,不属于正在执行任务,属于已经完成 任务)

第四步: 插入新任务 jbpm4_task 、插入新 任务历史记录 jbpm4_hist_task, 插入获得记录jbpm4_hist_actinst

第五步: 更新活动实例执行表 ,更新为下一节点 

3、 查看我的代办任务 ??? TaskService
查询jbpm4_task 条件是 ASSIGNEE  
TaskService taskService = Configuration.getProcessEngine().getTaskService();
// 部门经理的任务
List<Task> list = taskService.createTaskQuery().assignee("部门经理").list();
for (Task task : list) {
System.out.println("任务id :" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务操作人:" + task.getAssignee());
System.out.println("任务开始时间: " +task.getCreateTime().toLocaleString());
}

4、流程向后一部 
** 主要用于有分支的流程情况 
** 当task执行后,下一个节点有多个选择,通过向后一步,手动控制节点走向 
ProcessEngine processEngine = org.jbpm.api.Configuration.getProcessEngine();
processEngine.getExecutionService().signalExecutionById("流程执行实例id", "下一个transition的name属性");

====================================================================================
五、流程在运行过程中 变量信息 (传递问题)
1、 发布了一个流程定义后,能否查询出 png 流程描述图片
数据库提供大文本数据 Oracle CLOB 、MySQL 称为TEXT ; 提供大二进制 BLOB 
已知流程编号,能否通过编号,查询流程图片 ??
*** 通过Repository对象提供 getResourceAsStream("流程编号deploymentId","图片名称resourceName");

RepositoryService repositoryService = Configuration.getProcessEngine().getRepositoryService();
InputStream in = repositoryService.getResourceAsStream("1", "helloworld/helloworld.png"); // 读取图片
File file  = new File("d:/test.png");
FileUtils.copyInputStreamToFile(in, file);

2、 在流程运行过程中,设置与流程相关参数 
****** 只要是同一个流程对象,都可以获取这些参数 
设置一个变量信息,需要通过一个Service对象  
TaskService taskService = processEngine.getTaskService();
// 任务id 是 10002
Map<String,Object> variables = new HashMap<String,Object>();
variables.put("姓名", "张三");
variables.put("请假时间", "3天");
variables.put("原因", "感冒");
taskService.setVariables("10002", variables);

变量保存在 jbpm4_variable 

executionService.setVariable(executionId, name, value); // 设置一个值
executionService.setVariables(executionId, variablesMap); // 设置一个map

executionService.getVariable(executionId, variableName); 返回 Object  
executionService.getVariableNames(executionId);  返回 Set<String>
executionService.getVariables(s, set) ; // 返回 Map<String,Object> 

3、 设置流程中变量一些特殊时间点
1) 什么情况使用 executionService 设置变量 ? setVariables(executionId, variablesMap); 操作在节点中 
2) executionService.startProcessInstanceByKey(processDefinitionKey, variablesMap); 再启动流程实例时 设置变量 (为第一个节点提供)
3) taskService.completeTask(taskId, variablesMap);  在完成任务时设置变量 
/*
taskService.setVariables("10002", variables);
taskService.completeTask("10002");
*/
taskService.completeTask("10002", variables);

4、 能否向流程设置复杂的数据类型 ?? 
1) hibernate entity with a long id 必须是hibernate的一个实体 id是long
2) hibernate entity with a string id  必须是hibernate的一个实体 id是String 
***** 前两种 需要 编写hbm文件,在jbpm.hibernate.cfg.xml 中进行注册
3) serializable 只需要对对象实现Serializable接口 就可以了 

小结:
1、 GPD Myeclipse 插件安装
2、 jar包整合 (整合hibernate 3.6)
3、 流程定义 和 发布 (增删查 )
4、 流程执行(实例管理 )

5、 流程中变量数据 

宅急送项目的第七天笔记!(JBPM工作流)_第1张图片

宅急送项目的第七天笔记!(JBPM工作流)_第2张图片
宅急送项目的第七天笔记!(JBPM工作流)_第3张图片





















































你可能感兴趣的:(宅急送项目)