当前位置: 首页 > news >正文

Springboot +Flowable,流程表单应用之外置表单(JSON形式)(二)

一.简介

整体上来说,我们可以将Flowable 的表单分为三种不同的类型:

  1. 动态表单
    这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。
  2. 外置表单
    外置表单我们只需要定义一下表单的 key,至于这个 key 对应的表单是什么样子,则由开发者自己去维护。
  3. 内置表单
    这是内置的表单定义以及渲染引擎,

另外需要注意的,Flowable 中有很多不同类型的节点,但是只有开始节点和任务节点是支持表单定义的,其他节点均不支持表单定义

在前面的案例中,定义的表单使用了 HTML,实际上这个表单不仅可以使用 HTML,也可以使用 JSON 来定义表单

二.默认规则

使用 JSON 来定义 Flowable 表单,可以利用 Spring Boot 中的默认机制,即将表单文件置于 classpath:forms 目录下,那么在系统启动的时候,表单文件就会被自动部署。并且默认情况下,表单文件的后缀是 .form。

不过对于默认的表单文件位置和表单文件后缀,也可以通过在 application.properties 配置文件中添加如下内容进行修改,代码如下:

# 默认的表单文件后缀
flowable.form.resource-suffixes=**.form
# 默认的表单文件位置
flowable.form.resource-location=classpath*:/forms/

三.创建表单

还是以请假请求为例,创建一个表单文件,文件名为 application_form.form,代码如下:

{"key": "application_form.form","name": "经理审批表单","fields": [{"id": "days","name": "请假天数","type": "string","required": true,"placeholder": "empty"},{"id": "reason","name": "请假原因","type": "string","required": true,"placeholder": "empty"},{"id": "startTime","name": "开始时间","type": "date","required": true,"placeholder": "empty"},{"id": "endTime","name": "结束时间","type": "date","required": true,"placeholder": "empty"}]
}

这个 key 就是表单的唯一标识符,当有多个表单的时候,这个该值不可以重复,name 是表单是名称,fields 则定义了具体的字段,这里一共有四个。

在每一个 filed 的定义中,id 表示字段名,name 则是字段的中文名称,type 表示字段的类型,require 则表示这个字段是否是必填字段,placeholder 不用多说,跟我们日常使用的 input 标签中的 placeholder 的含义一致。

现在就创建好了。

注意:
由于 .form 文件,在 IDEA 中,默认会被当成 Swing 里边的 form 去处理,所以需要提前先用其他的编辑器写好 .form 文件,然后再拷贝到 IDEA 中即可。

四.创建流程

接下来创建一个流程图,流程中引用这个表单。流程图如下:
在这里插入图片描述
在流程图的三个 UserTask 中,分别通过如下方式去配置表单的标识:
在这里插入图片描述

最后下载这个流程图,将之放在 Spring Boot 项目的 classpath:/processes/ 目录下,这样当项目启动的时候,这个流程图会被自动部署。

五.测试

接下来,启动 Spring Boot 项目,启动之后,流程和表单都会被自动部署好,执行如下代码启动一个流程实例:

@Test
void contextLoads() {runtimeService.startProcessInstanceByKey("askforleave");
}

流程启动成功之后,进入到 提交请假申请 环节,该环节有一个表单需要填写,可以先通过如下代码来查看需要填写的表单内容:

@Test
void test01() {Task task = taskService.createTaskQuery().singleResult();FormInfo formInfo = taskService.getTaskFormModel(task.getId());SimpleFormModel formModel = (SimpleFormModel) formInfo.getFormModel();System.out.println("formInfo.getId() = " + formInfo.getId());System.out.println("formInfo.getName() = " + formInfo.getName());System.out.println("formInfo.getKey() = " + formInfo.getKey());List<FormField> fields = formModel.getFields();for (FormField field : fields) {System.out.println("field.getId() = " + field.getId());System.out.println("field.getName() = " + field.getName());System.out.println("field.getValue() = " + field.getValue());System.out.println("field.getType() = " + field.getType());System.out.println("===============");}
}

打印出来的内容如下:

formInfo.getId() = a5b1306a-5ab0-11ed-b35b-acde48001122
formInfo.getName() = 经理审批表单
formInfo.getKey() = application_form.form
field.getId() = days
field.getName() = 请假天数
field.getValue() = null
field.getType() = text
===============
field.getId() = reason
field.getName() = 请假原因
field.getValue() = null
field.getType() = text
===============
field.getId() = startTime
field.getName() = 开始时间
field.getValue() = null
field.getType() = date
===============
field.getId() = endTime
field.getName() = 结束时间
field.getValue() = null
field.getType() = date

打印出来的 value 都是 null,这是因为还没有填写表单。接下来先来完成提交请假申请 这一任务,代码如下:

@Test
void test02() {Task task = taskService.createTaskQuery().singleResult();Map<String, Object> vars = new HashMap<>();vars.put("days", 10);vars.put("reason", "玩一下");vars.put("startTime", "2022-10-10");vars.put("endTime", "2022-11-10");taskService.complete(task.getId(),vars);
}

完成之后,此时任务进入到 组长审批 这一环节,现在再去执行 test01 方法,此时查询的就是 组长审批 这个任务的表单信息,打印出来日志如下:

formInfo.getId() = a5b1306a-5ab0-11ed-b35b-acde48001122
formInfo.getName() = 经理审批表单
formInfo.getKey() = application_form.form
field.getId() = days
field.getName() = 请假天数
field.getValue() = 10
field.getType() = text
===============
field.getId() = reason
field.getName() = 请假原因
field.getValue() = 玩一下
field.getType() = text
===============
field.getId() = startTime
field.getName() = 开始时间
field.getValue() = 2022-10-10
field.getType() = date
===============
field.getId() = endTime
field.getName() = 结束时间
field.getValue() = 2022-11-10
field.getType() = date

此时都有对应的 value 了。

相关文章:

Springboot +Flowable,流程表单应用之外置表单(JSON形式)(二)

一.简介 整体上来说&#xff0c;我们可以将Flowable 的表单分为三种不同的类型&#xff1a; 动态表单 这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息&#xff0c;不过不能定义完整的表单页面。外置表单 外置表单我们只需要定义一下表单的 k…...

JavaScript如何使用if语句

JavaScript的if语句可以让我们根据某些条件来执行不同的代码块。使用if语句的基本思路是将要执行的代码放在括号内&#xff0c;并使用if关键字进行匹配。下面是一些例子&#xff1a; 简单的if语句&#xff1a; let age 18; if (age > 18) { console.log("You are…...

XSS攻击以及java应对措施

文章目录 一. XSS攻击介绍1. 前端安全2. xss攻击简介3. xss的攻击方式 二. java应对xss攻击的解决方案1. 强制修改html敏感标签内容2. 利用过滤器过滤非法html标签 一. XSS攻击介绍 1. 前端安全 随着互联网的高速发展&#xff0c;信息安全问题已经成为企业最为关注的焦点之一…...

yolo 训练

这里写目录标题 分配训练集&Validation数量数据集读取读取全部文件夹替换路径 loss weightNMSBBox_IOUEIou Optimizer 分配训练集&Validation数量 validation_size training_size * validation_ratio / (1 - validation_ratio)training_size 219 validation_ratio …...

谷歌chrome浏览器升级新版后字体显示不清楚解决方案

谷歌chrome浏览器升级新版后字体显示不清楚解决方案 参考图片&#xff1a; Chrome更新至版本Chrome 109.0.5414.120 字体看不清 浏览器症状与表现 Chrome更新至版本Chrome 109.0.5414.120 字体看不清&#xff1b;会很细&#xff0c;在设置中选择自定义的字体&#xff0c;仍无法…...

在外包干了三年,我废了……不吹不黑!

没错&#xff0c;我也干过外包&#xff0c;一干就是三年&#xff0c;三年后&#xff0c;我废了…… 虽说废的不是很彻底&#xff0c;但那三年我几乎是出差了三年、玩了三年、荒废了三年&#xff0c;那三年&#xff0c;我的技术能力几乎是零成长的。 说起这段三年的外包经历&a…...

【Vue】学习笔记-消息的订阅与发布

消息的订阅与发布(基本不用) 消息订阅与发布(pubsub)消息订阅与发布是一种组件间的通信的方式&#xff0c;适用于任意组件间通信 消息订阅与发布 1.订阅消息∶消息名 2.发布消息︰消息内容 消息订阅与发布的工作流程&#xff1a; &#xff08;A是订阅者&#xff0c;B是发布…...

大疆无人机 MobileSDK(遥控器/手机端)开发 v5版<1>

文章目录 概要整体架构流程技术细节SDK 架构体系概述层级架构智能任务空白项目集成 MSDK新建空白项目新建 MyApplication.kt 文件修改 build.gradle(Module) 文件修改 AndroidManifest.xml 文件修改 MainActivity.kt 文件导入 UXSDK 开源框架4.X 和 5.X 版本差异说明DJIKey差异…...

azkaban介绍

目录 为什么需要工作流调度系统 什么是azkaban azkaban适用场景 azkaban特点 常见的工作流调度系统 azkaban和Ooize特性对比 azkaban的架构 azkaban调度的任务有可能有那些类型 总结 为什么需要工作流调度系统 一个完整的大数据分析系统&#xff0c;必然由很多任务单…...

自学黑客(网络安全)必学内容

随着时代的发展&#xff0c;经济、社会、生产、生活越来越依赖网络。而随着万物互联的物联网技术的兴起&#xff0c;线上线下已经打通&#xff0c;虚拟世界和现实世界的边界正变得模糊。这使得来自网络空间的攻击能够穿透虚拟世界的边界&#xff0c;直接影响现实世界的安全。 …...

Java每日一练(20230518) 移除元素、跳跃游戏II、复原IP地址

目录 1. 移除链表元素 &#x1f31f; 2. 跳跃游戏 II &#x1f31f;&#x1f31f; 3. 复原 IP 地址 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 移…...

diff命令和vimdiff命令

文章目录 diff命令基本用法选项示例 vimdiff命令命令格式选项说明常用操作 diff命令 diff命令是一个文本比较工具&#xff0c;用于比较两个文件的内容&#xff0c;它会逐行比较两个文件的内容并输出它们之间的差异。下面是diff命令的常用选项和用法&#xff1a; 基本用法 比…...

AcWing 797.差分(C++)

目录 1.题目描述 2.AC 1.题目描述 797.差分 输入一个长度为 nn 的整数序列。 接下来输入 mm 个操作&#xff0c;每个操作包含三个整数 l,r,cl,r,c&#xff0c;表示将序列中 [l,r][l,r] 之间的每个数加上 cc。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两…...

Python每日一练(20230515) 只出现一次的数字 I\II\III

目录 1. 只出现一次的数字 Single Number 2. 只出现一次的数字 II Single Number II 3. 只出现一次的数字 III Single Number III &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 leetcod…...

基于【EasyDL】【图像分类】实现农作物病害识别小程序

内容、数据集来源:基于飞桨的农作物病害智能识别系统 - 飞桨AI Studio 项目背景 联合国粮食及农业组织的一份报告表明&#xff0c;每年农业生产的自然损失中有三分之一以上是由农业病虫害造成的&#xff0c;使这些成为当前影响农业生产和农业生产的最重要因素。需要考虑的农业…...

元宇宙又“死”了!Epic老板:你当6亿用户是摆设?

“扎克伯格花了数年时间试图让Metaverse成为现实&#xff0c;但现在它已被AI取代&#xff0c;并走向科技创意的坟墓。”一篇表达“元宇宙已死”的文章近期在推特上引发热议&#xff0c;而游戏制作公司Epic Games CEO Tim Sweeney的还击更是让这个话题热上加热。 “搞一次在线守…...

阶段小结2022

工作马上一年&#xff0c;对于一年工作能力提升可能逐步在提升&#xff0c;业务能力也在慢慢提升&#xff0c;虽然没有一年前想象的飞起状态&#xff0c;但是刚接触这一行&#xff0c;希望越来越好。 之前每次的遇到的问题其实都会在笔记或者博客中记录&#xff0c;但是没有整体…...

linux0.12-8-11-vsprintf.c

[383页] 1、 这一小节可以不看代码如何实现&#xff0c;因为标准的C库函数&#xff1b; 2、 等自己看完的这本书&#xff0c;有兴趣过来研究研究也是可以的。 8-11 vsprintf.c程序 8-11-1 功能描述 该程序主要包括vsprintf(),用于对参数产生格式化的输出。由于该函数是C函数…...

Node.js 与 WebAssembly

目录 1、简介 2、关键概念 3、生成WebAssembly模块 4、如何使用它 5、与操作系统交互 1、简介 首先&#xff0c;让我们了解为什么WebAssembly是一个很棒的工具&#xff0c;并学会自己使用它。 WebAssembly是一种类似汇编的高性能语言&#xff0c;可以从各种语言编译&…...

OpenCL编程指南-4.4矢量操作符

矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符&#xff08;加&#xff08;)、减&#xff08;–)、乘&#xff08;*&#xff09;和除&#xff08;/)&#xff09;&#xff0c;可以作用于内置整数、浮点标量和矢量数…...

数据库同步是什么意思?数据库架构有哪些?

目录 一、数据库同步是什么 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;数据库同步的类型 &#xff08;三&#xff09;数据库同步的实现方式 二、数据库架构的类型 &#xff08;一&#xff09;单机架构 &#xff08;二&#xff09;主从复制架构 &a…...

chili3d 笔记17 c++ 编译hlr 带隐藏线工程图

这个要注册不然emscripten编译不起来 --------------- 行不通 ---------------- 结构体 using LineSegment std::pair<gp_Pnt, gp_Pnt>;using LineSegmentList std::vector<LineSegment>; EMSCRIPTEN_BINDINGS(Shape_Projection) {value_object<LineSegment&g…...

思尔芯携手Andes晶心科技,加速先进RISC-V 芯片开发

在RISC-V生态快速发展和应用场景不断拓展的背景下&#xff0c;芯片设计正面临前所未有的复杂度挑战。近日&#xff0c;RISC-V处理器核领先厂商Andes晶心科技与思尔芯&#xff08;S2C&#xff09;达成重要合作&#xff0c;其双核单集群AX45MPV处理器已在思尔芯最新一代原型验证系…...

JVM中的各类引用

JVM中的各类引用 欢迎来到我的博客&#xff1a;TWind的博客 我的CSDN:&#xff1a;Thanwind-CSDN博客 我的掘金&#xff1a;Thanwinde 的个人主页 对象 众所不周知&#xff0c;Java中基本所有的对象都是分配在堆内存之中的&#xff0c;除开基本数据类型在栈帧中以外&#xf…...

怎么让大语言模型(LLMs)自动生成和优化提示词:APE

怎么让大语言模型(LLMs)自动生成和优化提示词:APE https://arxiv.org/pdf/2211.01910 1. 研究目标:让机器自己学会设计提示词 问题:大语言模型(如GPT-3)很强大,但需要精心设计的“提示词”才能发挥最佳效果。过去靠人工设计提示词,费时费力,还可能因表述差异导致模…...

Git 推送失败解决教程——error: failed to push some refs to

&#x1f6a7; Git 推送失败解决教程&#xff1a; 错误信息&#xff1a; error: failed to push some refs to ... hint: Updates were rejected because the remote contains work that you do not have locally.&#x1f9e0; 问题原因简述&#xff1a; 你的本地分支试图将…...

MS31912TEA 多通道半桥驱动器 氛围灯 照明灯 示宽灯 转向灯驱动 后视镜方向调节 可替代DRV8912

MS31912TEA 多通道半桥驱动器 氛围灯 照明灯 示宽灯 转向灯驱动 后视镜方向调节 可替代DRV8912 产品简述 MS31912 是集成多种高级诊断功能的多通道半桥驱动。 MS31912 具有 12 个半桥&#xff0c;典型工作电压 13.5V 下&#xff0c;每一个半桥支持 1A 电流&#xff0c;典型工…...

AOP实现Restful接口操作日志入表方案

文章目录 前言一、基础资源配置1.操作日志基本表[base_operation_log] 见附录1。2.操作日志扩展表[base_operation_log_ext] 见附录2。3.定义接口操作系统日志DTO&#xff1a;OptLogDTO4.定义操作日志注解类WebLog5.定义操作日志Aspect切面类SysLogAspect6.定义异步监听日志事件…...

Mysql的卸载与安装

确保卸载干净mysql 不然在进行mysal安装时候会出现不一的页面和问题 1、卸载 在应用页面将查询到的mysql相关应用卸载 2、到c盘下将残留的软件包进行数据删除 3、删除programData下的mysql数据 4、检查系统中的mysql是否存在 cmd中执行 sc deleted mysql80 5、删除注册表中的…...

CSS预处理器:Sass与Less的语法和特性(含实际案例)

Sass&#xff08;SCSS语法示例&#xff09; 1. 变量&#xff1a;统一管理颜色 // 定义变量 $primary-color: #1a237e; $success-color: #4caf50; $font-size-base: 16px;// 实际应用 body {color: $primary-color;font-size: $font-size-base; }.button {background: $succes…...