(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-valueUEL-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管理的类,我们可以进行多种多样的查询赋值,非常方便!

 

转载于:https://www.cnblogs.com/nfcm/p/6408481.html

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Activiti 是一种开源的工作流引擎,用于实现和管理业务流程。封装一个 Activiti 工作流引擎的 Demo 可以帮助我们更好地理解和使用这个工具。下面我将介绍如何封装一个 Activiti 工作流引擎的 Demo。 首先,我们需要在项目中引入 Activiti 的依赖,可以通过 Maven 或者手动导入 jar 包的方式。接下来,我们可以创建一个基于 Spring Boot 的应用程序。 在 Demo 中,我们需要定义一些基本的流程定义和流程实例。流程定义是一个流程模板,描述了业务流程的结构和步骤;而流程实例是流程定义的一个具体执行过程。 为了创建流程定义,我们需要使用 Activiti 提供的 ProcessEngineConfigurator 类。该类可以帮助我们初始化和配置 Activiti 引擎。在配置文件中,我们可以定义数据库连接信息、创建流程定义的方式以及其他相关配置。 在 Demo 中,我们可以使用 BPMN (Business Process Model and Notation)来定义流程模型。BPMN 是一种标准化的图形化表示语言,可以帮助我们更好地理解和管理业务流程。我们可以使用 Activiti 提供的设计器来创建和编辑 BPMN 文件。 接下来,我们需要实现流程定义的部署和启动。部署是将流程定义存储在 Activiti 引擎中的过程,启动是根据定义的流程模板创建一个流程实例。 我们可以使用 Activiti 提供的 RepositoryService 来进行部署操作。通过该服务,我们可以将 BPMN 文件部署到引擎中,并且可以查询已经部署的流程定义。 通过调用 RuntimeService 的 startProcessInstanceByKey 方法,我们可以根据流程定义的 key(在部署时定义的)启动一个流程实例。 在流程实例启动后,我们可以使用 TaskService 进行任务分配和处理。可以通过查询特定用户的待办任务和已完成任务,完成任务的提交操作。 最后,我们可以使用 HistoryService 来查询已完成的流程实例和任务的历史记录。这可以帮助我们进行流程性能和效率的评估。 封装一个 Activiti 工作流引擎的 Demo,可以帮助我们更好地了解和使用这个工作流引擎。通过实际的示例,我们可以学习如何创建流程定义、部署和启动流程实例、处理任务以及查询历史记录等操作。这将帮助我们更好地管理和优化业务流程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值