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分支/聚合活动

JBPM工作流(七)——详解流程图编程语言

 

  

?
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事件。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/12131.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论