【Flowable】使用UEL整合Springboot从0到1(四)

news2024/12/28 5:55:00

前言

在前面我们介绍了Springboot简单使用了foleable以及flowableUI的安装和使用,在之前我们分配任务的处理人的时候都是通过Assignee去指定固定的人的。这在实际业务中是不合适的,我们希望在流程中动态的去解析每个节点的处理人,当前flowable也支持这样去做。

一、 UEL表达式

Flowable使用UEL进行表达式解析。UEL代表Unified Expression Language,是EE6规范的一部分.Flowable支持两种UEL表达式: UEL-value 和UEL-method

  • UEL-value:值表达式 Value expression: 解析为一个值。默认情况下,所有流程变量都可以使用。
${userCode}
${isEndWorkFlag == true && isSnedEmailFlag == true}
# 这里userCode可以是任意值,员工号(编码),isEndWorkFlag和isSnedEmailFlag可以是boolean类型的值
  • UEL-method:将method方法注入到activiti的processEngineConfiguration的bean中。
${userService.findManagerUserCodeByEmpCode(empCode)}

# 这里userService就是我们spring当中的bean,这里先说明一下值表达式,后续整合spring的时候,在补充这块。

我们知道了UEL表达式之后,我们简单测试一下使用

二、使用FlowableUI绘制流程

在这里插入图片描述
绘制一个简单的流程,在分配人那里使用UEL表达式去指定节点处理人,绘制完成之后点击下载将流程下载下来,放置项目的resources下,这里有想尝试的可以直接使用如下MyHoliday.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef" exporter="Flowable Open Source Modeler" exporterVersion="6.7.2">
  <process id="MyHoliday" name="MyHoliday" isExecutable="true">
    <startEvent id="startEvent1" name="开始" flowable:formFieldValidation="true"></startEvent>
    <userTask id="sid-320C4AED-D9F4-4C53-B2B6-D4ACCBA155F5" name="直线审批" flowable:assignee="${firstAssigne}" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-422764E6-61F4-454A-BF08-9CF973E1E67D" sourceRef="startEvent1" targetRef="sid-320C4AED-D9F4-4C53-B2B6-D4ACCBA155F5"></sequenceFlow>
    <userTask id="sid-873E297E-9E6B-4F4E-AF6A-2E085F1806B1" name="部门审批" flowable:assignee="${deptAssigne}" flowable:formFieldValidation="true">
      <extensionElements>
        <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-A0869337-10D3-43BC-90C1-036C9719308E" sourceRef="sid-320C4AED-D9F4-4C53-B2B6-D4ACCBA155F5" targetRef="sid-873E297E-9E6B-4F4E-AF6A-2E085F1806B1"></sequenceFlow>
    <endEvent id="sid-CAB64925-F653-4167-8E12-ED956B723D2E" name="结束"></endEvent>
    <sequenceFlow id="sid-91D96B3A-3408-4504-A23D-8F0C2AFE19A7" sourceRef="sid-873E297E-9E6B-4F4E-AF6A-2E085F1806B1" targetRef="sid-CAB64925-F653-4167-8E12-ED956B723D2E"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_MyHoliday">
    <bpmndi:BPMNPlane bpmnElement="MyHoliday" id="BPMNPlane_MyHoliday">
      <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
        <omgdc:Bounds height="30.0" width="30.0" x="89.99999731779107" y="149.99999552965178"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-320C4AED-D9F4-4C53-B2B6-D4ACCBA155F5" id="BPMNShape_sid-320C4AED-D9F4-4C53-B2B6-D4ACCBA155F5">
        <omgdc:Bounds height="80.0" width="100.00000000000003" x="164.99999731779107" y="124.99999552965178"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-873E297E-9E6B-4F4E-AF6A-2E085F1806B1" id="BPMNShape_sid-873E297E-9E6B-4F4E-AF6A-2E085F1806B1">
        <omgdc:Bounds height="80.00000000000001" width="100.0" x="299.99999105930357" y="119.99999642372141"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-CAB64925-F653-4167-8E12-ED956B723D2E" id="BPMNShape_sid-CAB64925-F653-4167-8E12-ED956B723D2E">
        <omgdc:Bounds height="28.0" width="28.0" x="464.9999861419205" y="145.9999920725826"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-91D96B3A-3408-4504-A23D-8F0C2AFE19A7" id="BPMNEdge_sid-91D96B3A-3408-4504-A23D-8F0C2AFE19A7" flowable:sourceDockerX="50.0" flowable:sourceDockerY="40.00000000000001" flowable:targetDockerX="14.0" flowable:targetDockerY="14.0">
        <omgdi:waypoint x="399.94999034668683" y="159.99999473723344"></omgdi:waypoint>
        <omgdi:waypoint x="464.99998600932435" y="159.99999254311274"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-A0869337-10D3-43BC-90C1-036C9719308E" id="BPMNEdge_sid-A0869337-10D3-43BC-90C1-036C9719308E" flowable:sourceDockerX="50.000000000000014" flowable:sourceDockerY="40.0" flowable:targetDockerX="50.0" flowable:targetDockerY="40.00000000000001">
        <omgdi:waypoint x="264.9499973177909" y="163.1481439230865"></omgdi:waypoint>
        <omgdi:waypoint x="299.9999910593035" y="161.8499961786801"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-422764E6-61F4-454A-BF08-9CF973E1E67D" id="BPMNEdge_sid-422764E6-61F4-454A-BF08-9CF973E1E67D" flowable:sourceDockerX="15.0" flowable:sourceDockerY="15.0" flowable:targetDockerX="50.000000000000014" flowable:targetDockerY="40.0">
        <omgdi:waypoint x="119.94999580774865" y="164.99999552965178"></omgdi:waypoint>
        <omgdi:waypoint x="164.9999973177828" y="164.99999552965178"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

三、部署流程

    @Test
    public void testDeploy() {
        //1.获取ProcessEngine 对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //2.获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //3.完成流程部署操作
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("MyHoliday.bpmn20.xml") //关联要部署的流程名称
                .name("请假流程")
                .deploy(); //部署流程


        System.out.println("id: " + deploy.getId());
        System.out.println("name: " + deploy.getName());
        System.out.println("key: " + deploy.getKey());

    }

注意:ProcessEngines.getDefaultProcessEngine();该获取方式会去加载resources下的 flowable.cfg.xml文件,该文件为数据库的一些配置以及启动配置信息:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="processEngineConfiguration"
          class="org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <property name="jdbcUrl" value="jdbc:mysql://xxxxxx/flowable?allowMultiQueries=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false&amp;serverTimezone=UTC&amp;nullCatalogMeansCurrent=true" />
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUsername" value="xxx" />
        <property name="jdbcPassword" value="xxx" />
        <!--是否自动创建表-->
        <property name="databaseSchemaUpdate" value="true" />
        <!---是否启用异步任务-->
        <property name="asyncExecutorActivate" value="false" />
    </bean>
</beans>

不想使用该方法的也可以使用之前文章中的示例去进行创建ProcessEngine对象,如下:

 @Test
    public void testProcessEngine() {
        // 获取 ProcessEngineConfiguration 对象
        ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();

        //配置相关的数据库连接信息
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("xxxx");
        configuration.setJdbcPassword("xxxx");
        configuration.setJdbcUrl("jdbc:mysql://xxxxx/flowable?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
        //如果数据库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);

        //构建流程引擎对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        System.out.println("processEngine = " + processEngine);
    }

启动完成之后:
查询表ACT_RE_PROCDEF流程定义信息,上篇文章有介绍到flowable表的作用和注释,有兴趣的可以去看看。
在这里插入图片描述
这里

  • ID_:字段表示流程定义ID,可以理解成后续扩展版本控制的时候这个表示不同的版本号,
  • DEPLOYMENT_ID_:表示此次部署的ID

查询表:ACT_GE_BYTEARRAY 表的资源信息,可以看到我们绘制的xml文件一些信息
在这里插入图片描述

四、启动流程

 @Test
    public void startTest() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();


        Map<String, Object> variables = new HashMap<>();
		//部门处理人指定为张三处理firstAssigne为上述绘制指派人所填写的变量
        variables.put("firstAssigne", "张三");
        variables.put("deptAssigne", "李四");
		//MyHoliday:1:22504就是上面介绍到的 流程定义ID
        ProcessInstance processInstance = runtimeService.startProcessInstanceById("MyHoliday:1:22504", variables);


        System.out.println("processInstance.getProcessInstanceId() = " + processInstance.getProcessInstanceId());
    }

启动完成之后:
查询表: ACT_RU_VARIABLE查询我们决策变量。
在这里插入图片描述
查询表:ACT_RU_TASK可以看到我们当前流程的任务处理到哪了
在这里插入图片描述

五、审批操作

    @Test
    public void complete() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        TaskService taskService = defaultProcessEngine.getTaskService();
        taskService.setAssignee("25007", "张三");
        taskService.complete("25007");
    }

完成审批后可以看到act_ru_task表的节点达到部门审批了。
在这里插入图片描述
继续审批

    @Test
    public void complete01() {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();

        Task task = taskService.createTaskQuery()
                //流程实例ID很多地方可以拿ACT_RU_EXECUTION表中PROC_INST_ID_或者ACT_RU_TASK中的PROC_INST_ID_等等
                .processInstanceId("25001")
                .taskAssignee("李四")
                .singleResult();

        taskService.complete(task.getId());
    }

六、结束

经过上述操作,该流程已经完成了审批了。我们可以查询ACT_HI_ACTINST看到历史流程实例信息
在这里插入图片描述

本篇内容简单的介绍了一下从绘制流程到审批介绍的简单过程,如果有不正确或者不足的地方还恳请各位小伙伴给出一些建议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020727.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

家里电脑怎样远程办公室电脑?快解析映射域名实现内网穿透

远程电脑怎么操作是大家比较关注的问题&#xff0c;特别是涉及内外网&#xff0c;不在同一个局域网内不同计算机间的远程连接访问&#xff0c;如家里电脑怎样远程办公室电脑&#xff1f;这里提供一种简便的异地远程方法&#xff1a;用快解析。通过快解析映射域名软件&#xff0…

【漏洞复现】Smanga未授权远程代码执行漏洞(CVE-2023-36076) 附加SQL注入+任意文件读取

文章目录 前言声明一、产品简介一、漏洞描述二、漏洞等级三、影响范围四、漏洞复现五、修复建议六、附加漏洞漏洞一、SQL注入漏洞二、任意文件读取 前言 Smanga存在未授权远程代码执行漏洞,攻击者可在目标主机执行任意命令,获取服务器权限。 声明 请勿利用文章内的相关技术从…

【面试题】——Java基础篇(33题)

文章目录 1. 八大基本数据类型分类2. 重写和重载的区别3. int和integer区别4. Java的关键字5. 什么是自动装箱和拆箱&#xff1f;6. 什么是Java的多态性&#xff1f;7. 接口和抽象类的区别&#xff1f;8. Java中如何处理异常&#xff1f;9. Java中的final关键字有什么作用&…

Java文字描边效果实现

效果&#xff1a; FontUtil工具类的完整代码如下&#xff1a; 其中实现描边效果的函数为&#xff1a;generateAdaptiveStrokeFontImage() package com.ncarzone.data.contentcenter.biz.img.util;import org.springframework.core.io.ClassPathResource; import org.springfr…

爱思唯尔——利用AI来改善医疗决策和科研

爱思唯尔(Elsevier)是一家全球性的多媒体出版公司&#xff0c;为教育、专业科学和医疗社区提供20,000多种产品&#xff0c;其中包括《柳叶刀》和《细胞》等领先的研究出版物。 该公司正处于数字化转型的第一阶段&#xff0c;将公司140年中发表在报告和期刊上的大量数据数字化。…

小米华为,化干戈为玉帛!

近日来&#xff0c;手机圈又掀起了各大厂家推出新品的高潮。首先是华为Mate60的推出&#xff0c;其自研的麒麟9000S芯片瞬间点燃了国内手机市场&#xff0c;得到了国内甚至国外业界人士的认可和好评。 而近日网上盛传的小米创始人雷军的“愿意加入华为技术生态圈”的邀请&…

CRM客户管理软件对出海企业的帮助与好处

2023我们走出了疫情的阴霾&#xff0c;经济下行压力大&#xff0c;面对内需的不足&#xff0c;国内企业纷纷选择出海&#xff0c;拓展海外业务增加企业营收。企业出海不是一件易事&#xff0c;有了CRM系统可以让公司事半功倍&#xff0c;下面就来说一说CRM客户管理软件能为出海…

亚马逊应该怎么快速提升排名,获取review?

跨境电商做久了&#xff0c;卖家都会陷入一个困境&#xff0c;到底是该坚持慢慢做好&#xff0c;还是要测评&#xff1f; 现在跨境电商平台人人都在刷&#xff0c;不刷单想成功真的很难&#xff0c;不是没可能&#xff0c;但是选品要非常好&#xff0c;而且你的listing也要做好…

网络编程 day1

1->x.mind网络编程基础 2->简述字节序的概念&#xff0c;并用共用体&#xff08;联合体&#xff09;的方式计算本机的字节序 1.字节序是指不同类型的CPU主机&#xff0c;内存存储多字节整数序列的方式 2.小端字节序&#xff1a;低序字节存储在低地址上 3.大端字节序&a…

ROS 入门

目录 简介 ROS诞生背景 ROS的设计目标 ROS与ROS2 安装ROS 1.配置ubuntu的软件和更新 2.设置安装源 3.设置key 4.安装 5.配置环境变量 安装可能出现的问题 安装构建依赖 卸载 ROS架构 1.设计者 2.维护者 3. 立足系统架构: ROS 可以划分为三层 ROS通信机制 话…

007-第一代软件需求整理

第一代软件需求整理 文章目录 第一代软件需求整理项目介绍需求来源需求来源1&#xff1a;竞品软件分析需求来源2&#xff1a;医生&#xff08;市场&#xff09;需求来源3&#xff1a;项目组内部需求来源4&#xff1a;软件组内部需求来源5&#xff1a;软件开发成员需求来源6&…

Java精品项目源码第61期垃圾分类科普平台(代号V061)

Java精品项目源码第61期垃圾分类科普平台(代号V061) 大家好&#xff0c;小辰今天给大家介绍一个垃圾分类科普平台&#xff0c;演示视频公众号&#xff08;小辰哥的Java&#xff09;对号查询观看即可 文章目录 Java精品项目源码第61期垃圾分类科普平台(代号V061)难度指数&…

LeetCode: 4. Median of Two Sorted Arrays

LeetCode - The Worlds Leading Online Programming Learning Platform 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数&#xff0c;并且要求算法的时间复杂度为 O(log(m n))。 你可以假设 nums1 和 nums2 不会同时为空。 …

平衡二叉树删除结点后的调整操作

1.回顾插入操作 插入新结点后&#xff0c;要保持二叉排序树的特性不变&#xff08;左<中<右)若插入新结点导致不平衡&#xff0c;则需要调整平衡。 2.删除操作 删除结点后&#xff0c;要保持二叉排序树的特性不变&#xff08;左<中<右)若删除结点导致不平衡&…

华为aarch64架构的泰山服务器EulerOS 2.0 (SP8)系统离线安装saltstack3003.1实践

华为泰山服务器的CPU芯片架构为aarch64&#xff0c;所装系统为EulerOS 2.0 (SP8)aarch64系统&#xff0c;安装saltstack比较困难。本文讲解通过pip安装方式离线安装saltstack3003.1以进行集中化管理和维护。 一、系统环境 1、操作系统版本 [rootlocalhost ~]# cat /etc/os-r…

MyBatis字段名和属性名不一样的解决方案

一、给字段起别名&#xff0c;保持和属性名一样 <! --List<Emp> getAllEmp( ); --><select id"getAllEmp" resultType"Emp">select eid , emp_name empName , age , sex, email from t_emp</ select>如上面的SQL语句将emp_name取别…

蓝桥杯 题库 简单 每日十题 day4

01 津津上初中了。妈妈认为津津应该更加用功学习&#xff0c;所以津津除了上学之外&#xff0c;还要参加妈妈为她报名的各科复习班。另外每周妈妈还会送她去学习朗诵、舞蹈和钢琴。但是津津如果一天上课超过八个小时就会不高兴&#xff0c;而且上得越久就会越不高兴。假设津津…

产品解读 | 分布式多模数据库:KaiwuDB

1.KaiwuDB 是什么&#xff1f; KaiwuDB 是由浪潮创新研发的一款分布式、多模融合&#xff0c;支持原生 AI 的数据库产品&#xff0c;拥有“就地计算”等核心技术&#xff0c;具备高速写入、极速查询、SQL 支持、随需压缩、智能预计算、订阅发布、集群部署等特性&#xff0c;具…

DirectX12(d3d12)初始化

一、前置要求 Windows 10及以上(安装有DirectX12)VisualStudio 2022 二、DirectX12入门 1.引用头文件 #include<Windows.h> #include<d3d12.h> #include<dxgi1_4.h>2.注册窗口类并初始化窗口 这里我们调用Windows API 通过应用程序的句柄来注册一个唯一…

操作系统基本概念

目录 一、基本概述 二、操作系统的特点 &#xff08;一&#xff09;并发性&#xff08;实质是微观的串行、宏观的并行&#xff09; 1. 对比看&#xff1a;并行性 2. 单核CPU和多核CPU &#xff08;二&#xff09;共享性 &#xff08;三&#xff09;虚拟性 &#xff08;…