JBPM学习(六):详解流程图

简介: 本文主要详解流程图

最近发现这篇文章挺多人看的,也挺多人有疑问,我很想帮你们解答,但是很无奈,这篇文章只是我当时在自学时看的一个教程的记录,当时对JBPM也没有深入去学习,并且到现在也已经快4年了,这期间我都没用过JBPM,因此JBPM的东西我也忘得差不多了。庆幸的是我把当时看的教程保存了下来,因此如果对此文章有疑问的可以直接看JBPM的教程。另外,通过我分享的视频大家也能看到这是一个OA教程,我当时刚入门自学Java时就看过这个教程,这是一个使用Spring+Struts 2 +Hibernate框架搭建OA的教程,我自己觉得是一个很不错的教程,讲师的声音很好听,听了让人很舒服,特别适合新手。

 

作者更新于2020-06-04

 

 

 

概念:


流程图的组成:

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. AssignmentHandlerassignable.setAssignee(userId); // 指定当前任务的办理人(分配任务)

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

 

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

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


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


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


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


-->组任务的分配


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

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


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

 

<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

 

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

 

@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. 如果同时配置了expressionHandler,则expression有效,忽略Handler

vi. forkjoin分支/聚合活动

 

image.png

 

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时会有类转换异常。

 

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>)中,可以指定eventstartend,表示流程的开始与结束。

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

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

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

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

 

1.

<?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图,启动流程实例会执行3EventListenerImpl事件,结束流程实例也会执行3EventListenerImpl事件。

相关文章
|
1月前
|
API
工作流JBPM流程图说明
工作流JBPM流程图说明
24 0
|
1月前
|
XML 数据库 数据格式
工作流JBPM画图与配置
工作流JBPM画图与配置
27 0
|
8月前
|
数据库
23activiti - 流程变量(流程图)
23activiti - 流程变量(流程图)
29 0
|
XML 存储 API
工作流 jbpm(图文并茂)(下)
工作流 jbpm(图文并茂)
|
XML 存储 Java
工作流 jbpm(图文并茂)
工作流 jbpm(图文并茂)
|
存储 XML SQL
|
测试技术 数据库
|
XML 应用服务中间件 数据格式
Activiti入门操作
Activiti入门操作
|
Java 数据库连接
JBPM学习(一):实现一个简单的工作流例子全过程
本文主要讲实现一个简单的工作流例子全过程
301 0
JBPM学习(一):实现一个简单的工作流例子全过程