zoukankan      html  css  js  c++  java
  • JBPM 之介绍,使用

    JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。jBPM是公开源代码项目,它使用要遵循 Apache License,。

      jBPM在2004年10月18日,发布了2.0版本,并在同一天加入了JBoss,成为了JBoss企业中间件平台的一个组成部分,它的名称也改成JBoss jBPM。随着jBPM加入JBoss组织,jBPM也将进入一个全新的发展时代,它的前景是十分光明的。

      jBPM最大的特色就是它的商务逻辑定义没有采用目前的一些规范,如WfMC, XPDL, BPML, ebXML, BPEL4WS等,而是采用了它自己定义的JBoss jBPM Process definition language (jPdl)。jPdl认为一个商务流程可以被看作是一个UML状态图。jPdl就是详细定义了这个状态图的每个部分,如起始、结束状态,状态之间的转换,过图型化的流程定义,直观地描述业务流程。

      jBPM的另一个特色是它使用Hibernate来管理它的数据库。Hibernate是目前Java领域最好的一种数据存储层解决方案,只要是 Hibernate 支持的数据库, jBPM 也就支持.过Hibernate,jBPM将数据的管理职能分离出去,自己专注于商务逻辑的处理。

         JBPM由于各个版本之间差异比较大,所以在晚上找的很多资料跟自己使用的情况并不相符,很难找到一个完整的,能够运行的例子(Web程序例子)。
         本文以jbpm-starters-kit-3.1.2版本为例。下载地址:http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/j/project/jb/jbpm/jBPM%203/jbpm-3.1.2/。请下载:jbpm-starters-kit-3.1.2.zip版本,网上的参考资料比较多。
         OK,我们接下来讨论JBPM的流程图

    上图是一个比较完整的JBPM流程图(Finance中的子流程未写)。

     上图的XML定义代码:

    为方便大家Copy,所有代码均不显示行号
    <?xml version="1.0" encoding="UTF-8"?>
    <process-definition
    name="simple">
    <start-state name="start">
    <description>This process's name is simple</description>
    <task name="fill reimburse">
    <controller>
    <variable name="baoxiaoId" access="read,write,required" mapped-name="报销ID"/>
    </controller>
    </task>
    <transition name="" to="Manager"></transition>
    </start-state>
    <task-node name="Manager">
    <task name="department audit">
    <controller>
    <variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
    </controller>
    <assignment class="com.workflow.hander.ManagerAssignment"/>
    </task>
    <transition name="approve" to="AutoDecide"></transition>
    <transition name="requiremodify" to="Modify"></transition>
    <transition name="unapprove" to="Message"></transition>
    </task-node>
    <decision name="AutoDecide">
    <handler class="com.workflow.hander.ProcessDecision"/>
    <transition name="&lt;10000" to="Finance"></transition>
    <transition name="&gt;10000" to="Boss"></transition>
    </decision>
    <task-node name="Boss">
    <task name="boss audit">
    <controller>
    <variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
    </controller>
    <assignment class="com.workflow.hander.BossAssignment"/>
    </task>
    <transition name="approve" to="Finance"></transition>
    <transition name="unapprove" to="Message"></transition>
    </task-node>
    <process-state name="Finance">
    <sub-process name="finance"/>
    <variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
    <transition name="reimburse" to="Message"></transition>
    </process-state>
    <task-node name="Modify">
    <task name="modify reimburse">
    <controller>
    <variable name="baoxiaoId" access="read,write,required" mapped-name="报销ID"/>
    </controller>
    <assignment class="com.workflow.hander.UserAssignment"/>
    </task>
    <transition name="modified" to="Manager"></transition>
    <transition name="cancel" to="Message"></transition>
    </task-node>
    <node name="Message">
    <event type="node-enter">
    <action class="com.workflow.hander.ProcessResultAction"/>
    </event>
    <transition name="" to="end1"></transition>
    </node>
    <end-state name="end1"></end-state>
    </process-definition>

    涉及到的Java Handler:

    View Code
    //在start完成之后触发此Handler
    public class ManagerAssignment implements AssignmentHandler {

    public void assign(Assignable assignable, ExecutionContext executionContext)
    throws Exception {

    List<TbUser> list=new TbUserDAO().findByUserType(1);
    String [] manager=new String[list.size()];
    int i=0;
    for (Iterator<TbUser> iter = list.iterator(); iter.hasNext();) {
    TbUser el = (TbUser)iter.next();
    manager[i++]=el.getUserId()+"";
    }
    assignable.setPooledActors(manager);
    }

    }
    //在Manager审批完成之后(approve)触发此Handler
    public class ProcessDecision implements DecisionHandler {

    public String decide(ExecutionContext executionContext) throws Exception {

    String baixiaoId=executionContext.getContextInstance().getVariable("baoxiaoId").toString();
    TbBaoxiao baoxiao=new TbBaoxiaoDAO().findById(new Integer(Integer.parseInt(baixiaoId)));
    Set<TbBaoXiaoItem> bxItem=baoxiao.getTbBaoXiaoItems();
    int count=0;
    for (Iterator<TbBaoXiaoItem> iter = bxItem.iterator(); iter.hasNext();) {
    TbBaoXiaoItem item = (TbBaoXiaoItem) iter.next();
    count+=Integer.parseInt(item.getItemMoney());
    }
    if(count>10000)
    {
    return ">10000";
    }
    return "<10000";
    }

    }
    //在 Decision判断之后>1000时触发此Handler
    public class BossAssignment implements AssignmentHandler {

    public void assign(Assignable assignable, ExecutionContext executionContext)
    throws Exception {

    List<TbUser> list=new TbUserDAO().findByUserType(2);
    String [] boss=new String[list.size()];
    int i=0;
    for (Iterator<TbUser> iter = list.iterator(); iter.hasNext();) {
    TbUser el = (TbUser) iter.next();
    boss[i++]=el.getUserId()+"";
    }
    assignable.setPooledActors(boss);
    }
    }
    //Manager审批unapprove时出发的Handler
    public class UserAssignment implements AssignmentHandler {

    private static final long serialVersionUID = 1L;

    public void assign(Assignable assignable, ExecutionContext executionContext)
    throws Exception {

    String issueUser = executionContext.getContextInstance().getVariable("issueUser").toString();
    assignable.setActorId(issueUser);
    }

    }
    //所有task结束之后触发此Handler给创建者发送Message,然后end
    public class ProcessResultAction implements ActionHandler {

    public void execute(ExecutionContext executionContext) throws Exception {

    String baoxiaoId=executionContext.getContextInstance().getVariable("baoxiaoId").toString();
    TbBaoxiaoDAO baoxiaoDao=new TbBaoxiaoDAO();
    TbBaoxiao baoxiao=baoxiaoDao.findById(new Integer(Integer.parseInt(baoxiaoId)));
    String issueUser=baoxiao.getTbUser().getUserName();
    baoxiao.setBaoxiaoDate(new Date());

    List<TbApprove> list=new TbApproveDAO().findByApproveByBaoxiaoId(baoxiao.getBaoxiaoId());
    String result="驳回";
    if(list.iterator().hasNext())
    {
    TbApprove tbapp=(TbApprove) list.iterator().next();
    result=tbapp.getApproveResult();
    }
    baoxiao.setBaoxiaoFlag((result.indexOf("不同意")!=-1?"驳回":"批准"));
    baoxiaoDao.merge(baoxiao);
    StringBuffer message=new StringBuffer();
    message.append(issueUser+":您好! ");
    message.append("您申请的"+baoxiao.getBaoxiaoTitle());
    message.append("已经被"+(result.indexOf("不同意")!=-1?"驳回":"批准"));

    Message msg=new TextMessage(message.toString());
    msg.setDestination(issueUser);
    msg.setToken(executionContext.getProcessInstance().getRootToken());

    DbMessageService msgService=new DbMessageService();
    msgService.send(msg);
    msgService.close();
    }
    }

    使用的数据表(除了JBPM自身以外的表):

    View Code
    CREATE TABLE tb_approve (approve_id INTEGER NOT NULL AUTO_INCREMENT, user_id INTEGER, baoxiao_id INTEGER, approve_result VARCHAR(30), approve_memo VARCHAR(300), approve_date DATETIME, PRIMARY KEY (approve_id));
    CREATE TABLE tb_baoxiao (baoxiao_id INTEGER NOT NULL AUTO_INCREMENT, user_id INTEGER, baoxiao_title VARCHAR(30), baoxiao_memo VARCHAR(30), baoxiao_date DATETIME, baoxiao_flag VARCHAR(30), PRIMARY KEY (baoxiao_id));
    CREATE TABLE tb_baoxiao_item (item_id INTEGER NOT NULL AUTO_INCREMENT, baoxiao_id INTEGER, item_name VARCHAR(30), item_money VARCHAR(100), PRIMARY KEY (item_id));
    CREATE TABLE tb_user (user_id INTEGER NOT NULL AUTO_INCREMENT, user_name VARCHAR(30), user_password VARCHAR(30), user_type INTEGER, PRIMARY KEY (user_id));
    ALTER TABLE tb_approve ADD INDEX FKD0C46A7C5C89B0A (baoxiao_id), ADD CONSTRAINT FKD0C46A7C5C89B0A FOREIGN KEY (baoxiao_id) REFERENCES tb_baoxiao (baoxiao_id);
    ALTER TABLE tb_approve ADD INDEX FKD0C46A7CD355B42A (user_id), ADD CONSTRAINT FKD0C46A7CD355B42A FOREIGN KEY (user_id) REFERENCES tb_user (user_id);
    ALTER TABLE tb_baoxiao ADD INDEX FKEC067E1ED355B42A (user_id), ADD CONSTRAINT FKEC067E1ED355B42A FOREIGN KEY (user_id) REFERENCES tb_user (user_id);
    ALTER TABLE tb_baoxiao_item ADD INDEX FKE2F5D8945C89B0A (baoxiao_id), ADD CONSTRAINT FKE2F5D8945C89B0A FOREIGN KEY (baoxiao_id) REFERENCES tb_baoxiao (baoxiao_id);

    /*
    -- test Data
    insert into tb_user(user_name,user_password,user_type)
    values('test','123',0);

    insert into tb_user(user_name,user_password,user_type)
    values('manager1','123',1);

    insert into tb_user(user_name,user_password,user_type)
    values('manager2','123',1);
    insert into tb_user(user_name,user_password,user_type)
    values('boss','123',2);

    insert into tb_user(user_name,user_password,user_type)
    values('caiwu','123',2);
    */

    以上资料具体的action和dao处理我就不贴代码了,直接说怎么进入下一个task。

    View Code

    Start、End state是JBPM其实和结束状态的两个必不可少的Node。

    task-node  

       一个task-node可以包含一个或多个task,这些task分配给特定的user。当流程执行到task-node时,task instance将会被创建,一个task对应一个task instance。task instances 创建后,task-node就处于等待状态。当所有的task instances被特定的user执行完毕后,将会发出一个新的signal 到token,即流程继续执行。

    state

      state是一个纯粹的wait state(等待状态)。它和task-node的区别就是它不会创建task instances。很典型的用法是,当进入这个节点时(通过绑定一个action到node-enter event),发送一条消息到外部的系统,然后流程就处于等待状态。外部系统完成一些操作后返回一条消息,这个消息触发一个signal 到token,然后流程继续执行。(不常用)

    decision

      当需要在流程中根据不同条件来判断执行不同路径时,就可以用decision节点。两种方法:最简单的是在transitions里增加 condition elements(条件),condition是beanshell script写的,它返回一个boolean。当运行的时候,decision节点将会在它的 leaving transitions里循环,同时比较 leaving transitions里的condition,最先返回'true'的condition,那个leaving transitions将会被执行;作为选择,你可以实现DecisionHandler接口,它有一个decide()方法,该方法返回一个 String(leaving transition的名字)。

    fork  

       fork节点把一条执行路径分离成多条同时进行(并发)的执行路径,每条离开fork节点的路径产生一个子token。

    join  

       默认情况下,join节点会认为所有到达该节点的token都有着相同的父token。join 节点会结束每一个到达该节点的token,当所有的子token都到达该节点后,父token会激活。当仍然有子token处于活动状态时,join 节点是wait state(等待状态)。

    node  

       node节点就是让你挂自己的action用的(注意:不是event触发!!),当流程到达该节点时,action会被执行。你的action要实现ActionHandler接口。同样,在你的action里要控制流程!

    欢迎加入我的QQ群(JAVA开发):216672921,程序 元 世界
  • 相关阅读:
    【转】sublime text 2 中文乱码解决办法
    vi使用入门指南
    【原创】基于部署映像服务和管理(DISM)修改映象解决WIN7 USB3.0安装时报错
    日语五十音图快速记忆法
    深度阅读:C语言指针,从底层原理到花式技巧,图文+代码透析
    全民热衷“合成大西瓜”,游戏外挂上热搜,不愧是程序员!
    零基础想要转行成为程序员?这几点你要知道
    恩怨纠缠的苹果和微信!苹果底层开源代码中包含兼容微信的代码,这是苹果偷学代码啦?
    好你个C语言,原来还有这么多副面孔!
    “熊孩子”乱敲键盘就攻破了Linux桌面,其父亲发现linux漏洞
  • 原文地址:https://www.cnblogs.com/icerainsoft/p/2245946.html
Copyright © 2011-2022 走看看