OA早就流行应用于办公自动化管理,软件行业的前辈们相比做过很多OA系统的开发。他们积累了非富的OA开发经验,以至于JBOSS开发出了一套专门针对OA系统开发的框架——jbpm。
OA使得办公自动化,那么jbpm就是为了使编写OA自动化(jbpm需要手动添加的代码比较少)。同时jbpm可以灵活定制办公流程与组件。功能十分强大,真是为了解放程序员的双手(去除那些不必要的重复性工作)。
Jbpm与OA项目,继续由汤阳光老师传授。开发经验非富的老师在讲课时都喜欢使用画图工具来讲解理论知识,流程图可以让同学们很快的了解理论结构,视觉化的威力非常大。汤兄讲课比较细致,常用的快捷键他也有讲解以及各方面操作细节。
一、工作流
什么是工作流?就是与某一工作相关的一整套操作流程呗!比如说网络购物的简单流程:
(图1)
是不是每家网购公司的订单处理流程都一样呢?当然不是,比如互动网(图书)与vancl(服装),vancl可以在有限时间内无条件退货。这就是工作流程中比较特殊的一项。所以针对不同的工作流程需要,jbpm提供了灵活的设计方案。
Jbpm的工作流管理系统,主要包含两方面:流程设计器、工作流引擎。工作流引擎是根据用户设计的工作流程,自动建表并执行工作流任务…。流程设计器是一大亮点,用户主要使用流程设计器来实现工作流的创建以及各任务之间的关系等。(就像画流程图一样)
二、jbpm流程设计器
汤兄先是直接编写“processdefinition.xml”配置文件,来实现(图1)中的流程。然后再使用流程设计器来完成(图1)的工作流程。两种方法相比,效率和直观性相差悬殊。我们就直接画图吧!
首先需要安装eclipse插件,关于jbmp插件的安装方法网上有很多。我们直接切入正题。
1.创建一个普通的Java工程。
2.在工程中的src目录上右键“new”->”other…”->”JBossjBPM”->”ProcessDefinition”。
3.打开“processdefinition.xml”(如果没有看到设计器,在文件上右键”Open With”->”jBPM”)。
4.添加如下图形:
5.为每个《TaskNode》添加name(属性面板General分页)为(图1)过程中的内容(非括号内容),添加actor(属性面板Assignment分页)为(图1)过程中的括号里的内容。
6.上面图形自动生成的“processdefinition.xml”配置文件内容为:
<?xml version="1.0" encoding="UTF-8"?> <process-definition xmlns="" name="test"> <start-state name="start-state1"> <task> <assignment actor-id="开始"></assignment> </task> <transition to="task-node1"></transition> </start-state> <task-node name="task-node1"> <task name="下订单"> <assignment actor-id="客户"></assignment> </task> <transition to="task-node2"></transition> </task-node> <task-node name="task-node2"> <task name="发货"> <assignment actor-id="公司"></assignment> </task> <transition to="task-node3"></transition> </task-node> <task-node name="task-node3"> <task name="收货"> <assignment actor-id="客户"></assignment> </task> <transition to="end-state1"></transition> </task-node> <end-state name="end-state1"></end-state> </process-definition> |
7.运行jbpm目录中的“jbpm-jpdl-3.2.2\server\start.bat”文件,在浏览器地址栏中输入http://localhost:8080/jbpm-console。
8.使用用户名与密码为“manager”登陆。
9.选择“Deploy a new process”(提前将工程中的“processdefinition.xml”、“gpd.xml”、“ processimage.jpg”添加到zip压缩文件),部署zip压缩文件。
10.在页面中会出现导入后的流程名称,选择旁边的“start”开始流程中的第一个任务(如果没有start,需要先signal。)。点击“end”结束第一个任务…。
11.选择左边的“Process Image”可以查看,流程图的执行过程。
OK就这么简单,我们没有参与编码工作!
三、jbpmAPI
我们使用编码实现上面的功能,以了解jbmpAPI的使用。
1.新建立一个普通JAVA工程。
2.将上面生成的三个文件,入到工程src的“helloworld”包中。
3.导入jbm目录下以及lib目录下的所有jar文件,部分jar文件在此无用。我只是不想一一列出这些jar文件。
4.在工程中添加一个类。
我们来看一下jbpm的工作流程:
1.部署流程定义:
@Test public void deploy() { //通过jbpm的配置文件创建jbpmContext工厂,并通过工厂创建一个jbpmContext实例。 JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //通过资源文件载入工作流程定义 ProcessDefinition pd = ProcessDefinition.parseXmlResource("helloworld/processdefinition.xml"); try { //部署工作流程定义 jbpmContext.deployProcessDefinition(pd); } catch (RuntimeException e) { //如果出现异常,则设置回滚标记。 jbpmContext.setRollbackOnly(); throw e; } finally{ //如果没出现异常则保存后关闭,否则回滚后关闭。 jbpmContext.close(); } } |
创建jbpmContext工厂有2种方式(6个方法):
(1).使用“processdefinition.xml”文件:
ProcessDefinition.parseXmlResource(String xml);
ProcessDefinition.parseXmlResource(String xmlResource);
ProcessDefinition.parseXmlInputStream(InputStream inputStream);
ProcessDefinition.parseXmlReader(Reader reader);
(2).使用zip文件,jbpm中的JBOSS WEB容器使用的是zip:
ProcessDefinition.parseParZipInputStream(ZipInputStream zipInputStream);
ProcessDefinition.parseParResource(String parResource);
3. 执行流程(流程实例)、启动/创建(signal)
@Test public void startProcessInstance() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); ProcessDefinition pd = jbpmContext.getGraphSession().findLatestProcessDefinition("helloworld"); //创建一个工作流程的实例,就像定义一个类实例一样。工作流程定义好比类,工作流程实例好比是类的实例。 ProcessInstance pi = pd.createProcessInstance(); //进入工作流 pi.getRootToken().signal(); jbpmContext.close(); } |
4.查看/获取 任务列表(某一任务节点,只能被对应Actor看到)
@Test public void getTaskList() { JbpmConfiguration jbpmCfg = JbpmConfiguration .getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 获取任务列表 List<TaskInstance> list = jbpmContext.getTaskList("客户"); for (TaskInstance item : list) { //下面每一行加个“//”是汤兄的技巧哦!~ Ctrl+Shift+F也改变不了它的排版。 System.out.println("id=" + item.getId()// + ",name=" + item.getName()// + ",actorId=" + item.getActorId()// + ",create=" + item.getCreate()// + ",start=" + item.getStart()// + ",end=" + item.getEnd()); } jbpmContext.close(); } |
5.开始/结束 办理任务
// 开始任务 @Test public void startTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 开一个任务 TaskInstance taskIns = jbpmContext.getTaskInstance(1); taskIns.start(); jbpmContext.close(); } // 结束任务 @Test public void endTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //结束一个任务,然后跳转到下一个任务 TaskInstance taskIns = jbpmContext.getTaskInstance(3); taskIns.end(); jbpmContext.close(); } |
6.4-5循环。
四、jbpm中的流程变量
一个工作流程中包含多个任务,比如上边的网购。客户生成了一个订单,店家需要处理订单并发货。这两个任务间就需要一个“订单变量”。
首先我们在工程中添加一个Order类(domain)。jbpm使用hibernate框架进行数据库操作,所以需要为Order类添加一个hibernate映射文件,并添加hibernate的配置文件。在jbpm中使用变量的代码如下:
添加变量:
@Test public void setVariable() { // 加载配置,创建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //获取流程定义 ProcessDefinition proDef = jbpmContext.getGraphSession() .findLatestProcessDefinition("helloworld"); ProcessInstance proIns = proDef.createProcessInstance(); //创建一个order对象并保存 Order order = new Order(); order.setName("*****jbpmVariableTest*****"); ContextInstance conIns = proIns.getContextInstance(); conIns.setVariable("order", order); proIns.getRootToken().signal(); //关闭后自动保存 jbpmContext.close(); } |
获取变量:
@Test public void getVariable() { // 加载配置,创建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 根据任务实例ID获取任务 TaskInstance task = jbpmContext.getTaskInstance(17); task.start(); //帮助JbpmContext分担工作的ContextInstance ContextInstance conIns = task.getProcessInstance().getContextInstance(); //获取变量 Order order = (Order) conIns.getVariable("order"); System.out.println(order.getName()); task.end(); jbpmContext.close(); } |
在总结jbpm的过程中还是遇到一些问题的,感觉jbpm比较大。今天是第一天学习它,希望在以后的学习课程中会掌握它。
加油!