(4)activiti之uel表达式
有了前面几章,我们肯定有一定的困惑,activiti如何与实际业务整合,比如一条采购单,如何跟一个流程实例互相关联起来?
这里就需要使用到activiti启动流程实例时设置一个流程实例的businessKey(一般存储我们一条采购单的id)
1,启动流程实例设置其businessKey
/**
* 启动一个流程实例,设置其业务id
*/
@Test
public void startProInsWithKey() {
RuntimeService runtimeService = engine.getRuntimeService(); String processDefinitionKey = "purchasingflow";
//设置一个businessKey,在我实际业务中可能是一个采购单,或者订单之类的id
String businessKey ="111";
// 根据流程定义的key启动一个流程实例
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey);
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId()); }
一般情况下,我们是在用户保存一条采购单的时候,启动这个实例,并且动态获取采购单的id(也就是用作流程实例的businessKey),并且我们还会在采购单表中保存这个流程实例的id,双向一对一绑定,方便业务查询
2,根据采购单的id(也就是用作流程实例的businessKey),动态的查询出对应的流程实例
/**
* 通过businessKey查询流程实例
*/
@Test
public void queryProInsWithKey(){
RuntimeService runtimeService = engine.getRuntimeService();
String businessKey ="111"; ProcessInstanceQuery instanceQuery = runtimeService.createProcessInstanceQuery();
//根据其流程定义key和业务id businessKey查询出对应的流程实例,一般只有一条
instanceQuery.processInstanceBusinessKey(businessKey);
//查询出唯一的一条流程实例
ProcessInstance processInstance = instanceQuery.singleResult(); System.out.println("流程实例id:"+processInstance.getId());
System.out.println("流程定义id:"+processInstance.getProcessDefinitionId()); }
到这里,我们就清楚了一个流程实例和实际业务数据的绑定
大家到这里也启动了很多的流程实例了,发现我们的任务办理人都是写死为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 = engine.getRuntimeService(); 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:" + processInstance.getId());
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId()); }
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 = engine.getRuntimeService(); 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:" + processInstance.getId());
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId()); }
3,到这里流程实例启动成功,我们观察数据库的当前任务表,观察第一个节点的处理人是否为我们设置的101的userId

设置成功!
(二)演示uel-method
执行步骤
1,设置节点的执行人为${method.getUserNameByUserId(userId)} ,其中method方法是我们注入到spring中的一个类,userId是我们设置的全局变量
2,将method方法注入到activiti的processEngineConfiguration的bean中(在我们的activiti.cfg.xml中)
3,启动一个流程设置全局变量userId作为启动参数,看看是否走到这个节点的处理人是我们method方法getUserNameByUserId返回的name
好了,直接上代码
1,设置节点,重新部署流程定义

2,method的java方法和activiti.cfg.xml的注入配置
public class CommonMethod{
public String getUserNameByUserId(int userId){
return "activiti"+userId;
}
}
<bean class="cn.nfcm.po.CommonMethod" id="commonmethod"></bean>
<bean id="processEngineConfiguration"
class="org.activiti.engine.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 = engine.getRuntimeService(); 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:" + processInstance.getId());
System.out.println("流程定义id:" + processInstance.getProcessDefinitionId()); }
到这里我们会发现流程启动成功,并且流程的当前任务处理人为acitiviti8,在实际的应用中因为都是spring管理的类,我们可以进行多种多样的查询赋值,非常方便!
(4)activiti之uel表达式的更多相关文章
- (4)activiti工作流引擎之uel表达式
有了前面几章,我们肯定有一定的困惑,activiti如何与实际业务整合,比如一条采购单,如何跟一个流程实例互相关联起来? 这里就需要使用到activiti启动流程实例时设置一个流程实例的busines ...
- activiti工作流引擎之uel表达式
qq讨论群:313032825本人做了一个微信公众号,用于分享各类视频学习资源和我多年学习经验,喜欢的可以关注哦! 有了前面几章,我们肯定有一定的困惑,activiti如何与实际业务整合,比如一条采购 ...
- Activiti流量变量(九)
1什么是流程变量 流程变量在 activiti 中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和 activiti结合时少不了流程变量,流程变量就是 activiti 在管理工作流时根据 ...
- Activiti的分配任务负责人(八)
1分配任务负责人 1.1 固定分配 在进行业务流程建模时指定固定的任务负责人 在 properties 视图中,填写 Assignee 项为任务负责人.注意事项由于固定分配方式,任务只管一步一步执行任 ...
- Activiti任务分配
分配任务负责人 一.固定分配 在进行业务流程建模时指定固定的任务负责人 在properties 视图中,填写Assignee 项为任务负责人. 注意: 由于固定分配方式,任务只管一步一步执行任务,执行 ...
- activiti学习笔记二
上一篇文章大概讲了下什么是流程引擎,为什么我们要用流程引擎,他的基本原理是啥,以及怎么进行基本的使用,这篇文章我们再讲下其他的一些使用. 删除流程部署 package activiti02; impo ...
- activiti知识点梳理
一.Activiti是什么 Alfresco 软件在 2010 年 5 月17 日宣布 Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理 BPM的专家 Tom Ba ...
- Activiti7 任务人员动态分配(理论)
之前一直用的流程模型都是,固态的,写死的 由于固定分配方式,任务只能一步一步执行,执行到每一个任务将按照bpmn的配置去分配任务负责人.这显然在实际开发中是不可能的 所以我们需要动态分配人员 表达式分 ...
- Activiti源码浅析:Activity与Task
最近由于接触到Activiti工作流引擎,因此粗读了一下它的源码. 总结了一些内容如下,这些内容一般的doc上都是没有提及的. 1. model.Activity与model.Task Activit ...
随机推荐
- 《数据结构与算法分析:C语言描述》读书笔记------List的C语言实现
List的简单实现.在GCC下测试通过. list.h #ifndef _List_H /*List数据结构的简单实现*/ struct Node; typedef struct Node Node; ...
- iOS正则表达式 分类: ios技术 2015-07-14 14:00 35人阅读 评论(0) 收藏
一.什么是正则表达式 正则表达式,又称正规表示法,是对字符串操作的一种逻辑公式.正则表达式可以检测给定的字符串是否符合我们定义的逻辑,也可以从字符串中获取我们想要的特定部分.它可以迅速地用极简单的方式 ...
- 【转】gvim配置及相关插件安装
0.准备软件及插件.(a)gvim72.exe 地址ftp://ftp.vim.org/pub/vim/pc/gvim72.exe.(b)vimcdoc-1.7.0-setup.exe 地址http: ...
- 外部SRAM实验,让STM32的外部SRAM操作跟内部SRAM一样(转)
源:外部SRAM实验,让STM32的外部SRAM操作跟内部SRAM一样 前几天看到开源电子论坛(openedv.com)有人在问这个问题,我特意去做了这个实验,这样用外部SRAM就跟用内部SRAM一样 ...
- 使用Linux自定义自动补全命令完善自己的shell脚本
对于Linuxer来说,自动补全是再熟悉不过的一个功能了.当你在命令行敲下部分的命令时,肯定会本能地按下Tab键补全完整的命令,当然除了命令补全之外,还有文件名补全. Bash-completion ...
- shell相关命令
1.shell是什么? 从用户角度:shell是用户与Linux沟通的桥梁 从程序员角度:shell本身是一种用C语言编写的程序 shell担任了翻译的角色,将用户输入的命令翻译成Linux能够识别的 ...
- iOS 之 NSUserDefault
1. 概念 NSUserDefaults是一种特殊的property list.是系统封装的属性列表,方便记录简单的数据. 2. 使用说明 2.1. 创建NSUserDefaults NSUserDe ...
- php绘图-报表
1.PHP报表的创建,通过绘图,过程 要先开启gb库, 可以使用jpgraph(绘图框架)快速制作一些图形 报表的作用:可以制作一些统计图,地形图,分布图等,还可以做验证码图片(通过在画布上加字和干扰 ...
- Angular - - $templateCache 和 $templateRequest
$templateCache 第一次使用模板,它被加载到模板缓存中,以便快速检索.你可以直接将模板标签加载到缓存中,或者通过$templateCache服务. 通过script标签: <scri ...
- js模块化开发——require.js的用法详细介绍(含jsonp)
RequireJS的目标是鼓励代码的模块化,它使用了不同于传统<script>标签脚本加载步骤.可以用它回事.优化代码,但其主要的目的还是为了代码的模块化.它鼓励在使用脚本以moudle ...