(4)activiti⼯作流引擎之uel表达式
有了前⾯⼏章,我们肯定有⼀定的困惑,activiti如何与实际业务整合,⽐如⼀条采购单,如何跟⼀个流程实例互相关联起来?
这⾥就需要使⽤到activiti启动流程实例时设置⼀个流程实例的businessKey(⼀般存储我们⼀条采购单的id)
1,启动流程实例设置其businessKey
spring framework runtime/**
* 启动⼀个流程实例,设置其业务id
*/
@Test
public void startProInsWithKey() {
RuntimeService runtimeService = RuntimeService();
String processDefinitionKey = "purchasingflow";
//设置⼀个businessKey,在我实际业务中可能是⼀个采购单,或者订单之类的id
String businessKey ="111";
// 根据流程定义的key启动⼀个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey);
System.out.println("流程实例id:" + Id());
System.out.println("流程定义id:" + ProcessDefinitionId());
}
⼀般情况下,我们是在⽤户保存⼀条采购单的时候,启动这个实例,并且动态获取采购单的id(也就是⽤作流程实例的businessKey),并且我们还会在采购单表中保存这个流程实例的id,双向⼀对⼀绑定,⽅便业务查询
2,根据采购单的id(也就是⽤作流程实例的businessKey),动态的查询出对应的流程实例
/
**
* 通过businessKey查询流程实例
*/
@Test
public void queryProInsWithKey(){
RuntimeService runtimeService = RuntimeService();
String businessKey ="111";
ProcessInstanceQuery instanceQuery = ateProcessInstanceQuery();
//根据其流程定义key和业务id businessKey查询出对应的流程实例,⼀般只有⼀条
instanceQuery.processInstanceBusinessKey(businessKey);
//查询出唯⼀的⼀条流程实例
ProcessInstance processInstance = instanceQuery.singleResult();
System.out.println("流程实例id:"+Id());
System.out.println("流程定义id:"+ProcessDefinitionId());
}
到这⾥,我们就清楚了⼀个流程实例和实际业务数据的绑定
⼤家到这⾥也启动了很多的流程实例了,发现我们的任务办理⼈都是写死为zhangsan,lisi之类的,那么我们可以动态的指定吗,这就需要使⽤到我们的uel表达式了
⾸先uel表达式到底是什么呢?
UEL是java EE6规范的⼀部分,UEL(Unified Expression Language)即统⼀表达式语⾔,activiti⽀持两个UEL表达式:UEL-value和UEL-method。我们都会分别做介绍(⼀)我们先来演⽰uel-value
⾸先做个简单的使⽤带⼤家⼊门
使⽤步骤:(看不明⽩的运⾏下⾯的代码⾛⼀遍再回头看)
1,在任务的节点,不直接指定处理⼈的id,设置处理⼈表达式${assignee},并且重新部署流程定义
2, 启动⼀个流程实例是设置启动变量动态设置assignee的值
3,查看并验证下⼀个任务的处理⼈是否为我们动态设置
1,⾸先我们设置节点
2,在启动代码时动态设置assignee的值
/**
* 启动流程实例时设置全局变量
*/
@Test
public void startProInsWithArgs(){
RuntimeService runtimeService = RuntimeService();
String processDefinitionKey = "purchasingflow";
//设置其启动的全局变量参数,其value可以是javabean,也可以是普通字符串,数字
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("assignee", "feige");
/
/设置流程启动时,设置参数启动
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
System.out.println("流程实例id:" + Id());
System.out.println("流程定义id:" + ProcessDefinitionId());
}
3,这个时候我们通过查看数据库,查看act_ru_task当前运⾏的任务,查看
从上⾯的我们可以看到流程⾛到了,创建采购单,并且采购的assignee处理⼈为feige
因为当我们⾛到了创建采购单时,会从当前流程实例的全局变量查name为assignee的值,如果查询到,则将这个assignee的值赋给这个节点,如果我们动态设置了,但是⾛到这个节点前(为什么说节点前呢,因为还可以在别的时候设置变量,后⾯的章节会讲)
没有到这个assignee变量的值,会报错的,⼤家可以⾃⼰试⼀试
当然除了上⾯的设置⽅法,我们还有其他的设置⽅法来动态设置其节点的值吗?答案是肯定的,启动的流程时候的参数的value,不仅仅可以是String类型,还可以是Object对象(序列化的),Map,List,Array
我们这⾥采⽤对象做演⽰,执⾏步骤如下
1,设置流程的第⼀个节点动态的值为${user.userId},他会默认查变量name为user的对应的值的getUserId获取值,重新部署流程定义
2,启动流程时,设置这个user的javabean到流程的全局变量中
3,查看⾛到这个节点的当前任务的处理⼈是否是我们user的userId变量的值
1,设置节点
2,设置javabean  User对象并且在流程实例启动时设置进去
public class User implements Serializable{
/**
* ⽤于序列化
*/
private static final long serialVersionUID = 7717000074223077256L;
private String userId;
private String sex;
private String name;
public User(String userId, String sex, String name) {
super();
this.userId = userId;
this.sex = sex;
this.name = name;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 启动流程设置⼀个user⽤户到全局变量中
*/
@Test
public void startProInsWithObj(){
RuntimeService runtimeService = RuntimeService();
String processDefinitionKey = "purchasingflow";
//设置其启动的全局变量参数,其value设置为user对象,这⾥写死
User user = new User("101","男","张三");
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("user", user);
//设置流程启动时,设置参数启动
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
System.out.println("流程实例id:" + Id());
System.out.println("流程定义id:" + ProcessDefinitionId());
}
3,到这⾥流程实例启动成功,我们观察数据库的当前任务表,观察第⼀个节点的处理⼈是否为我们设置的101的userId
设置成功!
(⼆)演⽰uel-method
执⾏步骤
1,设置节点的执⾏⼈为${UserNameByUserId(userId)} ,其中method⽅法是我们注⼊到spring中的⼀个类,userId是我们设置的全局变量
2,将method⽅法注⼊到activiti的processEngineConfiguration的bean中(在我们的l中)
3,启动⼀个流程设置全局变量userId作为启动参数,看看是否⾛到这个节点的处理⼈是我们method⽅法getUserNameByUserId返回的name
好了,直接上代码
1,设置节点,重新部署流程定义
2,method的java⽅法和l的注⼊配置
public class CommonMethod{
public String getUserNameByUserId(int userId){
return "activiti"+userId;
}
}
<bean class="cn.nfcm.po.CommonMethod" id="commonmethod"></bean>
<bean id="processEngineConfiguration"
class="ine.impl.cfg.StandaloneProcessEngineConfiguration">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- activiti数据库表处理策略 -->
<property name="databaseSchemaUpdate" value="true"/>
<!-- 可以注⼊多个类到activiti的beans中,其中key对应的就是我们的类名 -->
<property name="beans">
<map>
<entry key="commonmethod" value-ref="commonmethod"/>
</map>
</property>
</bean>
3,启动⼀个流程实例
/**
* 根据⽅法得到值
*/
@Test
public void startProInsWithMethod(){
RuntimeService runtimeService = RuntimeService();
String processDefinitionKey = "purchasingflow";
//这⾥设置userId为8,⾛到第⼀个节点会查我们注⼊进去的commonmethod的getUserNameByUserId⽅法并传递userId
Map<String,Object> variables = new HashMap<String, Object>();
variables.put("userId", 8);
//设置流程启动时,设置参数启动
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
System.out.println("流程实例id:" + Id());
System.out.println("流程定义id:" + ProcessDefinitionId());
}
到这⾥我们会发现流程启动成功,并且流程的当前任务处理⼈为acitiviti8,在实际的应⽤中因为都是spring管理的类,我们可以进⾏多种多样的查询赋值,⾮常⽅便!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。