• JBPM工作流(七)——详解流程图


    概念:

    流程图的组成:

    a. 活动 Activity / 节点 Node

    b. 流转 Transition / 连线(单向箭头)

    c. 事件

    1.流转(Transition)

      a) 一般情况一个活动中可以指定一个或多个Transition

        i. 开始活动(Start)中只能有一个Transition。

        ii. 结束活动(End)中没有Transition。

        iii. 其他活动中有一条或多条Transition

      b) 如果Transition只有一个,则可以不指定名称(名称是null);如果有多个,则要分别指定唯一的名称。

    2.活动(Activity)

      a) 流转控制活动(预定义活动)

      

       

                i. start开始活动

              代表流程的开始边界,一个流程有且只能有一个Start活动。开始活动只能指定一个Transition。在流程实例启动后,会 自动的使用这个唯一的Transition离开开始活动,到一下个活动。

        ii. end/end-error/end-cancel(结束活动)

          代表流程的结束边界,可以有多个,也可以没有。如果有多个,则到达任一个结束活动,整个流程就都结束了;如果没 有,则到达最后那个没有Transition的活动,流程就结束了。

               iii. state状态活动

          作用:等待。可以使用signal使其结束等待,并向后执行一步。

             

        iv. task任务活动

    -->个人任务的分配

      

     

        1. 使用流程变量:assignee="#{manager}"

        2. AssignmentHandler:assignable.setAssignee(userId); // 指定当前任务的办理人(分配任务)

          a) 需要在.jbdl.xml的<task>元素中写

          

    1
    <assignment-handler class="cn.grace.AssignmentHandlerImpl"/>

          b) 指定的AssignmentHandlerImpl类要实现AssignmentHandler接口

          c) 在AssignmentHandlerImpl类中可以使用assignable.setAssignee(userId),分配个人任务。

        3. TaskService.assignTask(taskId, userId)// 把指定的任务分配给指定的人

          

    1
    processEngine.getTaskService().assignTask(taskId, userId);

      -->组任务的分配

        1.  使用流程变量:assignee="#{userIdsString}" // 要是String型的变量,多个候选人之前用','隔开

        2. AssignmentHandler:assignable.addCandidateUser(userId);// 添加组任务的候选人

          a) 需要在.jbdl.xml的<task>元素中写

          

    1
    <assignment-handler class="cn.grace.GroupTaskAssignmentHandlerImpl"/>

         b) 指定的AssignmentHandlerImpl类要实现AssignmentHandler接口

         c) 在AssignmentHandlerImpl类中可以使用assignable.addCandidateUser(userId),添加组任务候选人。

         3. TaskService.addTaskParticipatingUser(taskId,userId,Participation.CANDIDATE);//添加组任务的候选人

      v. Decision判断活动

        1. 使用expression,如:expr="#{'to state2'}"

        2. 使用Handler,在Handler Class里配置指定的DecisionHandlerImpl类的路径

        DecisionHandlerImpl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class DecisionHandlerImpl implements DecisionHandler {
     
        // 计算离开当前节点用的Transition的名称并返回
        @Override
        public String decide(OpenExecution execution) {
            System.out.println("DecisionHandlerImpl.decide()");
            // 获取业务数据
            Integer days = (Integer) execution.getVariable("请假天数");
            // 选择Transition
            if (days > 7) {
                return "to 总经理审批";
            } else {
                return "to end1";
            }
        }
    }

      ProcessTest.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Test
    public void test() {
        // 1,部署流程定义
        InputStream in = this.getClass().getResourceAsStream("test.jpdl.xml"); // 当前类所在包中的文件
        processEngine.getRepositoryService()//
                .createDeployment()//
                .addResourceFromInputStream("test.jpdl.xml", in)//
                .deploy();
     
        // 2,启动流程实例
        Map<String, Object> variables = new HashMap<String, Object>();
        // variables.put("请假天数", 10);启动流程实例后,进行到to 总经理审批环节。
        variables.put("请假天数", 3);//启动流程实例后,进行到to end1环节。
        ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey("test", variables);
    }

      此时,如果variables.put("请假天数", 3);启动流程实例后,进行到to end1环节。

      此时,如果variables.put("请假天数", 10);启动流程实例后,进行到to 总经理审批环节。

    3. 如果同时配置了expression与Handler,则expression有效,忽略Handler。

      vi. fork、join分支/聚合活动


      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class ProcessTest {
     
        private ProcessEngine processEngine = Configuration.getProcessEngine();
     
        @Test
        public void test() {
            // 1,部署流程定义
            InputStream in = this.getClass().getResourceAsStream("test.jpdl.xml"); // 当前类所在包中的文件
            processEngine.getRepositoryService()//
                    .createDeployment()//
                    .addResourceFromInputStream("test.jpdl.xml", in)//
                    .deploy();
     
            // 2,启动流程实例
            ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey("test");
            System.out.println("processInstanceId = " + pi.getId());
            System.out.println("当前正在执行的活动:" + pi.findActiveActivityNames());
        }
    }

      输出结果为:

        processInstanceId = test.330007

        当前正在执行的活动:[汇款, 发货]

        可以看出,汇款和发货同时执行中。并且,只有当2条路线都到join活动,流程才会继续往后执行。

      b) 自定义活动(custom)

        i. 在<custom>元素中指定class属性为指定的类ExternalActivityBehaviourImpl

        ii. 这个类要实现ExternalActivityBehaviour接口,其中有两个方法:

          1. execute(ActivityExecution):节点的功能代码

    2. signal(ActivityExecution, String, Map):在当前节点等待时,外部发信号时的行为

    3. 在execute()方法中,可以调用以下方法对流程进行控制

      a) ActivityExecution.waitForSignal():在当前节点等待。
      b) ActivityExecution.takeDefaultTransition():使用默认的Transition离开,当前节点中定义的第一个为默认的。
      c) ActivityExecution.take(String transitionName):使用指定的Transition离开
      d) ActivityExecution.end():结束流程实例
    4. 也可以实现ActivityBehaviour接口,只有一个方法execute(ActivityExecution),这样就不能等待,否则signal时会有类转换异常。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class ExternalActivityBehaviourImpl implements ExternalActivityBehaviour {
     
        // 到达这个活动时执行的方法
        @Override
        public void execute(ActivityExecution execution) throws Exception {
            System.out.println("已发送信息.");//此处写自己要执行的事件
     
            // 默认是执行完代码后离开当前活动,不会执行signal方法,也可以写如下代码
            // execution.takeDefaultTransition(); // 离开当前活动
     
            // // 使用指定名称的Transition离开当前活动
            // execution.take(transitionName);
     
            // 执行完后不要离开,而是要等待外部调用signal()方法时才离开
            execution.waitForSignal();
        }
     
        // 调用signal()方法离开当前节点前执行的方法(如果在execute()中直接离开当前节点了,这个方法就不会被执行)
        @Override
        public void signal(ActivityExecution execution, String signalName, Map<String, ?> parameters) throws Exception {
            System.out.println("ExternalActivityBehaviourImpl.signal()");
        }
    }

      

    3.事件

    a) 在根元素中,或在节点元素中,使用<on event="">元素指定事件,其中event属性代表事件的类型。

    b) 在<on>中用子元素<event-listener class="EventListenerImpl" />,指定处理的类,要求指定的类要实现EventListener接口

    c) 事件类型:

    i. <on>元素放在根元素(<process>)中,可以指定event为start或end,表示流程的开始与结束。

    ii. <on>元素放在节点元素中,可以指定event为start或end,表示节点的进入与离开

    iii. 在Start节点中只有end事件,在End节点中只有start事件。

    iv. 在<transition>元素中直接写<event-listener class="">,就是配置事件。(因为在这里只有一个事件,所以不用写on与类型)

    v. 在<task>元素中还可以配置assign事件,是在分配任务时触发的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <?xml version="1.0" encoding="UTF-8"?>
     
    <process name="test" xmlns="http://jbpm.org/4.4/jpdl">
     
        <!-- 流程实例的启动事件 -->
        <on event="start">
            <event-listener class="cn.grace.EventListenerImpl"></event-listener>
        </on>
        <!-- 流程实例的结束事件 -->
        <on event="end">
            <event-listener class="cn.grace.EventListenerImpl"></event-listener>
        </on>
     
        <start name="start1" g="86,69,7,1">
            <!-- 开始活动中只有离开活动的事件 -->
            <on event="end">
                <event-listener class="cn.grace.EventListenerImpl"></event-listener>
            </on>
            <transition name="to task1" to="task1" g="-53,-17" />
        </start>
     
        <task name="task1" g="61,171,92,52" assignee="张三">
            <!-- 进入活动的事件 -->
            <on event="start">
                <event-listener class="cn.grace.EventListenerImpl"></event-listener>
            </on>
            <!--离开活动的事件 -->
            <on event="end">
                <event-listener class="cn.grace.EventListenerImpl"></event-listener>
            </on>
            <transition name="to end1" to="end1" g="-47,-17" />
        </task>
     
        <end name="end1" g="86,272,48,48">
            <!-- 结束活动中只有进入活动的事件 -->
            <on event="start">
                <event-listener class="cn.grace.EventListenerImpl"></event-listener>
            </on>
        </end>
    </process>

      根据上述.jpdl.xml和对应的.png图,启动流程实例会执行3次EventListenerImpl事件,结束流程实例也会执行3次EventListenerImpl事件。

  • 相关阅读:
    2015总结篇
    Android应用性能优化实践
    Android国外学习资源汇总
    直接拿来用!十大Material Design开源项目
    selenium12-读取文件 excel
    selenium11-自动化练习读取文件txt
    selenium10-python3部分代码复习
    selenium09-自动化练习案例
    selenium08-测试用例模块化与数据分离
    selenium07-处理 alter 对话框
  • 原文地址:https://www.cnblogs.com/HHR-SUN/p/7235878.html
Copyright © 2020-2023  润新知