首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

转:传智播客-Jbpm(5)

2012-10-21 
转:传智播客--Jbpm(五)1. 组任务和个人任务组任务拾取个人任务审批2. 增加2个实体请假单:LeaveForm, 审批

转:传智播客--Jbpm(五)
1. 组任务和个人任务
  
    组任务      拾取
    个人任务    审批

2. 增加2个实体
    请假单:LeaveForm, 审批信息:ApproveInfo;
    2者是1对多的关系;

    LeaveForm:
        id:long;

        creator:User;
        processName:String;
        processInstanceId : long;(不使用外键关联,会导致级联删除)
        creationTime:Date;
        status:int
        approveInfos : Set<ApproveInfo> ;
        -----------------------
        days:int;
        reason : String;


    ApproveInfo:
        id : long;
        leaveForm : LeaveForm;
        workItem : long;(任务实例,变量命名, TaskInstance)
        -----------------------
        approval : boolean;
        comment : String;
        approver : User;
        approveTime : Date;
    用户与请假单是一对多关系;
    用户与审批信息室一对多关系;

    增加报销表单:
    发现与请假表单的属性很接近;
    所以抽取成父类:业务表单
    请假表单和报销表单继承业务表单
    请假表单:days:int, reason:String

    所以修改审批表单关联的业务表单属性
        bizForm : BizForm
        取代
        leaveForm : LeaveForm;

    练习:
        继承关系的映射文件的写法;
  
    问题:
        long id;
        long processInstanceId;

        (1) 流程变量与临时变量;
            流程变量需要被保存到数据库中;
            class that are persistable with hibernate;
        (2) 流程定义的删除功能;
            删除流程定义,就删除了所有使用该流程定义的流程实例;(jbpm设置的)
            并删除这些流程实例中的所有任务实例;
            流程实例的删除不能【删除业务表单/解除关系】;
            这样导致外键约束失败;
            所以processInstanceId不与流程实例在数据库关系上关联;
            但它保存的还是真实的processInstanceId;
            这样如果该流程实例没有被删除,则通过processInstanceId可以查找到流程实例;
            如果该流程实例被删除,就不能被查到;
        
3. 根据分析,写WorkflowAction extends BaseAction;
    applyUI(), apply()  -- 表单填写与提交
    listWorkitems()     -- 列车当前用户的工作项(任务实例)列表;
    takeWorkitem()      -- 拾取任务
    approveUI           -- 审批页面
    approve             -- 审批

    首先以请假为例;写出上述代码;
  
    (1) 获取当前登录用户:
        BaseAction.getCurrentUser();
    (2) 显示任务列表;
        任务名字,所属流程,发起人,发起时间,相关操作;
      
        action中的变量使用
        Map<TaskInstance, BizForm> tasks;

        <c:forEach item="${tasks}" var="entry">
        <c:set var="workitem" value="{entry.key}"   scope="page">
        <c:set var="bizForm"  value="{entry.value}" scope="page">

        <fmt:formateDate var="" pattern="" />
      
        <c:remove var="workitem" scope="page">
        <c:remove var="bizForm" scope="page">

    (3)登录页面的处理
        放在一个小窗口中,登录成功后
        -- 提示登录成功;
        -- 刷新主页面:
            window.opener.document.location.reload(true);
        -- 关闭自己;

        问题:登录上去后,不能显示用户名,可能与缓存有关;

    (4) 组任务与个人任务的区分
        ${workitem.actorId eq null} 拾取
        ${workitem.actorId ne null} 审批

来源:(http://blog.sina.com.cn/s/blog_5ecfe46a0100dos6.html) - 传智播客--Jbpm(五)_hhl_bj_新浪博客
    (5) 拾取任务;
        takeWorkItem(long workItemId, Strint actorId);
            ti = jbpm.getTaskInstance(workItemId);
            ti.setActorId(actorId);
  
    (6) 如何强制用户登录?
        父类:BaseAction.execute
        a. 判断当前用户是否登录;如果未登录,则重定向到
            response.sendRedirect(request.getContextPath("/")+"/user.do?method=loginUI");
            return null;
        b. 判断当前的方法是否为login, loginUI,避免死循环;
            requestParameter("method");
            methodName.startsWith("login");
        c. 其他 return super.execute(...);

    (7) 拾取与审批操作中的细节:
        拾取或审批成功后,与登录的处理方法接近;

    (8) 审批的业务
        保存审批信息;
        如果审批不通过,流程结束,业务表单为审批未通过状态;
        如果审批通过,流程继续执行;
            如果本次审批时最后一个环节,业务表单为审批通过状态;

        // 审批部通过
        ti.getProcessInstance().end();
        bizForm.setStatus(BizForm.STATUS_DISAPPROVED);

        // 如何知道下一个结点是结束结点:通过时间
        if (ti.getProcessInstance().getEnded() )
            bizForm.setStatus(BizForm.STATUS_APPROVED);


    (9) 任务执行与传播的问题:
        部门经理审批未通过时,任务还继续走向总经理审批;
        但流程已经结束(从数据库中可以查看);

        -- 审批不通过
        t1.start();
        ti.setSignalling(false);  // 增加这样的代码,是否发信号往下执行,默认为true;
        ti.end();

        -- 审批通过
        t1.start();
        t1.end();

    (10) 请假的流程有很多代码可以重用,结合报销流程,实现代码重用;
        分析代码重用

        -- 包含页面
            <c:import url="">
        -- Action中很多方法实现重用,但是不同的流程跳转的页面地址不一样;
            所以写一个工具类,通过流程名来获取跳转页面名;

           new ActionForward(FormViewUtils.getView(bizForm.getProcessName()));


    (11) 流程实例监控
        2个方法:正在执行的流程实例列表;查看流程实例图片;

        getSession().createQuery(
            "from ProcessInstance pi where pi.end is null").list();
        ProcessInstance : 需要在Hibernate-mapping auto-import="true / false"
        auto-import="false" : 引用时需要使用全名
            org.jbpm.graph.exe.ProcessInstance
      
        查询时可用使用hql语句,修改删除时要使用它自带的api;

        图片高亮的思路:
            用流程图作为背景图片;
            用一个div,它的大小与正在执行的节点相等,修改它的颜色即可;

            <html:img action="/pd?method=viewPdImage&id=${pi.processDefinition.id}"
                style="position: absolute; left:0; top:0;"
            />

            如何找到结点的坐标信息;
                // 获取结点名
                String nodeName = pi.getRootToken().getNode().getName();
      
                //
                InputStream in = pi.getProcessDefinition().getFileDefinition.getInputStream("");

                SAXReader saxReader = new SAXReader();
                Document doc = saxReader.read(in);
                in.close();
                Element root = doc.getRootElement();
                for (Iterator it = root.elementIterator("node"); it.hasNext();) {
                    Element e = it.next();
                    if ( e.getName().equals(nodeName) ) {
                        int x = Integer.parseInt( e.attribute("x").getValue());
                        int y = Integer.parseInt( e.attribute("y").getValue());
                        int width = Integer.parseInt( e.attribute("width").getValue());
                        int height = Integer.parseInt( e.attribute("height").getValue());
                      
                        rect = new Rectangle(x, y, width, height);
                }
              
                request.setAttribute("rect", rect);
              
                <div style="border:red; position:absolute; left:{rect.x};
                    top:${rect.y}; width:${rect.width}; height:${rect.height}>
              
                div生成,但是位置信息为空,应该是Action中的rect为null;
                可能是结点没有找到;
                dom4j, css

                多个Token的情况;
                    fox, join结点
                    也就是查找所有的结点;
                    pi.findAllToken();
                    List<Rectangle> positions = new ArrayList<Rectangle>();
                    for (Object obj : pi.findAllTokens()) {
                        Token token = (Token) obj;
                        String nodeName = token.getNode().getName();
                        Rectangele position = findPosition(root, nodeName);
                        positions.add(position);
                    }




热点排行