• activiti工作流引擎之uel表达式


    qq讨论群:313032825
    本人做了一个微信公众号,用于分享各类视频学习资源和我多年学习经验,喜欢的可以关注哦!
    公众号图片

    有了前面几章,我们肯定有一定的困惑,activiti如何与实际业务整合,比如一条采购单,如何跟一个流程实例互相关联起来?

    这里就需要使用到activiti启动流程实例时设置一个流程实例的businessKey(一般存储我们一条采购单的id)

    1,启动流程实例设置其businessKey

    复制代码
    /**
         * 启动一个流程实例,设置其业务id
         */
        @Test
        public void startProInsWithKey() {
            RuntimeService runtimeService = engine.getRuntimeService();
    
        String processDefinitionKey </span>= "purchasingflow"<span style="color: #000000;">;
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置一个businessKey,在我实际业务中可能是一个采购单,或者订单之类的id</span>
        String businessKey ="111"<span style="color: #000000;">;
        </span><span style="color: #008000;">//</span><span style="color: #008000;"> 根据流程定义的key启动一个流程实例</span>
        ProcessInstance processInstance =<span style="color: #000000;"> runtimeService.startProcessInstanceByKey(processDefinitionKey,businessKey);
        System.out.println(</span>"流程实例id:" +<span style="color: #000000;"> processInstance.getId());
        System.out.println(</span>"流程定义id:" +<span style="color: #000000;"> processInstance.getProcessDefinitionId());
    
    }</span></pre>
    
    复制代码

     一般情况下,我们是在用户保存一条采购单的时候,启动这个实例,并且动态获取采购单的id(也就是用作流程实例的businessKey),并且我们还会在采购单表中保存这个流程实例的id,双向一对一绑定,方便业务查询

    2,根据采购单的id(也就是用作流程实例的businessKey),动态的查询出对应的流程实例

    复制代码
    /**
         * 通过businessKey查询流程实例
         */
        @Test
        public void queryProInsWithKey(){
            RuntimeService runtimeService = engine.getRuntimeService();
            String businessKey ="111";
    
        ProcessInstanceQuery instanceQuery </span>=<span style="color: #000000;"> runtimeService.createProcessInstanceQuery();
        </span><span style="color: #008000;">//</span><span style="color: #008000;">根据其流程定义key和业务id businessKey查询出对应的流程实例,一般只有一条</span>
    

    instanceQuery.processInstanceBusinessKey(businessKey);
    //查询出唯一的一条流程实例
    ProcessInstance processInstance = instanceQuery.singleResult();

        System.out.println(</span>"流程实例id:"+<span style="color: #000000;">processInstance.getId());
        System.out.println(</span>"流程定义id:"+<span style="color: #000000;">processInstance.getProcessDefinitionId());
        
    }</span></pre>
    
    复制代码

    到这里,我们就清楚了一个流程实例和实际业务数据的绑定

    大家到这里也启动了很多的流程实例了,发现我们的任务办理人都是写死为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 </span>=<span style="color: #000000;"> engine.getRuntimeService();
    
        String processDefinitionKey </span>= "purchasingflow"<span style="color: #000000;">;
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置其启动的全局变量参数,其value可以是javabean,也可以是普通字符串,数字</span>
        Map&lt;String,Object&gt; variables = <span style="color: #0000ff;">new</span> HashMap&lt;String, Object&gt;<span style="color: #000000;">();
        variables.put(</span>"assignee", "feige"<span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置流程启动时,设置参数启动</span>
        ProcessInstance processInstance =<span style="color: #000000;"> runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
        System.out.println(</span>"流程实例id:" +<span style="color: #000000;"> processInstance.getId());
        System.out.println(</span>"流程定义id:" +<span style="color: #000000;"> processInstance.getProcessDefinitionId());
        
    }</span></pre>
    
    复制代码

    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;
    
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> User(String userId, String sex, String name) {
        </span><span style="color: #0000ff;">super</span><span style="color: #000000;">();
        </span><span style="color: #0000ff;">this</span>.userId =<span style="color: #000000;"> userId;
        </span><span style="color: #0000ff;">this</span>.sex =<span style="color: #000000;"> sex;
        </span><span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;
    }
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String getUserId() {
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> userId;
    }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setUserId(String userId) {
        </span><span style="color: #0000ff;">this</span>.userId =<span style="color: #000000;"> userId;
    }
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String getSex() {
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> sex;
    }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setSex(String sex) {
        </span><span style="color: #0000ff;">this</span>.sex =<span style="color: #000000;"> sex;
    }
    </span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String getName() {
        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> name;
    }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> setName(String name) {
        </span><span style="color: #0000ff;">this</span>.name =<span style="color: #000000;"> name;
    }
    

    }

    复制代码
    复制代码
    /**
         * 启动流程设置一个user用户到全局变量中
         */
        @Test
        public void startProInsWithObj(){
    
        RuntimeService runtimeService </span>=<span style="color: #000000;"> engine.getRuntimeService();
    
        String processDefinitionKey </span>= "purchasingflow"<span style="color: #000000;">;
        
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置其启动的全局变量参数,其value设置为user对象,这里写死</span>
        User user = <span style="color: #0000ff;">new</span> User("101","男","张三"<span style="color: #000000;">);
        
        Map</span>&lt;String,Object&gt; variables = <span style="color: #0000ff;">new</span> HashMap&lt;String, Object&gt;<span style="color: #000000;">();
        variables.put(</span>"user"<span style="color: #000000;">, user);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置流程启动时,设置参数启动</span>
        ProcessInstance processInstance =<span style="color: #000000;"> runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
        System.out.println(</span>"流程实例id:" +<span style="color: #000000;"> processInstance.getId());
        System.out.println(</span>"流程定义id:" +<span style="color: #000000;"> processInstance.getProcessDefinitionId());
        
    }</span></pre>
    
    复制代码

    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{
    
    </span><span style="color: #0000ff;">public</span> String getUserNameByUserId(<span style="color: #0000ff;">int</span><span style="color: #000000;"> userId){
        
        </span><span style="color: #0000ff;">return</span> "activiti"+<span style="color: #000000;">userId;
        
    }
    

    }

    复制代码
    复制代码
    <bean class="cn.nfcm.po.CommonMethod" id="commonmethod"></bean>
    
    <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">bean </span><span style="color: #ff0000;">id</span><span style="color: #0000ff;">="processEngineConfiguration"</span><span style="color: #ff0000;">
        class</span><span style="color: #0000ff;">="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"</span><span style="color: #0000ff;">&gt;</span>
        <span style="color: #008000;">&lt;!--</span><span style="color: #008000;"> 数据源 </span><span style="color: #008000;">--&gt;</span>
        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="dataSource"</span><span style="color: #ff0000;"> ref</span><span style="color: #0000ff;">="dataSource"</span> <span style="color: #0000ff;">/&gt;</span>
        <span style="color: #008000;">&lt;!--</span><span style="color: #008000;"> activiti数据库表处理策略 </span><span style="color: #008000;">--&gt;</span>
        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="databaseSchemaUpdate"</span><span style="color: #ff0000;"> value</span><span style="color: #0000ff;">="true"</span> <span style="color: #0000ff;">/&gt;</span>
        <span style="color: #008000;">&lt;!--</span><span style="color: #008000;"> 可以注入多个类到activiti的beans中,其中key对应的就是我们的类名 </span><span style="color: #008000;">--&gt;</span>
        <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">property </span><span style="color: #ff0000;">name</span><span style="color: #0000ff;">="beans"</span><span style="color: #0000ff;">&gt;</span>
            <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">map</span><span style="color: #0000ff;">&gt;</span>
                <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">entry </span><span style="color: #ff0000;">key</span><span style="color: #0000ff;">="commonmethod"</span><span style="color: #ff0000;"> value-ref</span><span style="color: #0000ff;">="commonmethod"</span> <span style="color: #0000ff;">/&gt;</span>
            <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">map</span><span style="color: #0000ff;">&gt;</span>
        <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">property</span><span style="color: #0000ff;">&gt;</span>
    <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">bean</span><span style="color: #0000ff;">&gt;</span></pre>
    
    复制代码

    3,启动一个流程实例

    复制代码
    /**
         * 根据方法得到值
         */
        @Test
        public void startProInsWithMethod(){
    
        RuntimeService runtimeService </span>=<span style="color: #000000;"> engine.getRuntimeService();
    
        String processDefinitionKey </span>= "purchasingflow"<span style="color: #000000;">;
        </span><span style="color: #008000;">//</span><span style="color: #008000;">这里设置userId为8,走到第一个节点会查找我们注入进去的commonmethod的getUserNameByUserId方法并传递userId</span>
        Map&lt;String,Object&gt; variables = <span style="color: #0000ff;">new</span> HashMap&lt;String, Object&gt;<span style="color: #000000;">();
        variables.put(</span>"userId", 8<span style="color: #000000;">);
        
        </span><span style="color: #008000;">//</span><span style="color: #008000;">设置流程启动时,设置参数启动</span>
        ProcessInstance processInstance =<span style="color: #000000;"> runtimeService.startProcessInstanceByKey(processDefinitionKey,variables);
        System.out.println(</span>"流程实例id:" +<span style="color: #000000;"> processInstance.getId());
        System.out.println(</span>"流程定义id:" +<span style="color: #000000;"> processInstance.getProcessDefinitionId());
        
        
    }</span></pre>
    
    复制代码

    到这里我们会发现流程启动成功,并且流程的当前任务处理人为acitiviti8,在实际的应用中因为都是spring管理的类,我们可以进行多种多样的查询赋值,非常方便!

    原文地址:https://www.cnblogs.com/nfcm/p/6408481.html
  • 相关阅读:
    Java Servlet 入门: 旧版本Eclipse配置兼容新版本Tomcat。
    Java Servlet 入门: 问题系列:Filter中通过HttpServletRequest.getParts()获取不到上传文件。
    开源:Taurus.MVCJava 版本框架 (支持javax.servlet.*和jakarta.servlet.*双系列,内集成微服务客户端)
    Java Servlet 入门: 问题系列:Filter request.getRequestDispatcher(url).forward(...,...)映射请求后404。
    Java Servlet 入门: Eclipse运行Web程序:去掉Url中的开头的项目名称。
    RabbitMQ 入门系列:6、保障消息:不丢失:发送方、Rabbit存储端、接收方。
    Taurus.MVCJava 版本打包上传到Maven中央仓库(详细过程):4、Maven项目转换与pom.xml配置
    Taurus.MVC 微服务框架 入门开发教程:项目集成:6、微服务间的调用方式:Rpc.StartTaskAsync。
    Java Servlet 入门: 重复注解的使用。
    Java Servlet 入门: 问题系列:警告: Web应用程序[ROOT]似乎启动了一个名为[Thread1]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪
  • 原文地址:https://www.cnblogs.com/jpfss/p/11103128.html
Copyright © 2020-2023  润新知