Springboot +Flowable,流程表单应用之外置表单(JSON形式)(二)
一.简介
整体上来说,我们可以将Flowable 的表单分为三种不同的类型:
- 动态表单
这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。 - 外置表单
外置表单我们只需要定义一下表单的 key,至于这个 key 对应的表单是什么样子,则由开发者自己去维护。 - 内置表单
这是内置的表单定义以及渲染引擎,
另外需要注意的,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形式)(二)
一.简介 整体上来说,我们可以将Flowable 的表单分为三种不同的类型: 动态表单 这种表单定义方式我们可以配置表单中每一个字段的可读性、可写性、是否必填等信息,不过不能定义完整的表单页面。外置表单 外置表单我们只需要定义一下表单的 k…...
JavaScript如何使用if语句
JavaScript的if语句可以让我们根据某些条件来执行不同的代码块。使用if语句的基本思路是将要执行的代码放在括号内,并使用if关键字进行匹配。下面是一些例子: 简单的if语句: 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. 前端安全 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一…...
yolo 训练
这里写目录标题 分配训练集&Validation数量数据集读取读取全部文件夹替换路径 loss weightNMSBBox_IOUEIou Optimizer 分配训练集&Validation数量 validation_size training_size * validation_ratio / (1 - validation_ratio)training_size 219 validation_ratio …...
谷歌chrome浏览器升级新版后字体显示不清楚解决方案
谷歌chrome浏览器升级新版后字体显示不清楚解决方案 参考图片: Chrome更新至版本Chrome 109.0.5414.120 字体看不清 浏览器症状与表现 Chrome更新至版本Chrome 109.0.5414.120 字体看不清;会很细,在设置中选择自定义的字体,仍无法…...
在外包干了三年,我废了……不吹不黑!
没错,我也干过外包,一干就是三年,三年后,我废了…… 虽说废的不是很彻底,但那三年我几乎是出差了三年、玩了三年、荒废了三年,那三年,我的技术能力几乎是零成长的。 说起这段三年的外包经历&a…...
【Vue】学习笔记-消息的订阅与发布
消息的订阅与发布(基本不用) 消息订阅与发布(pubsub)消息订阅与发布是一种组件间的通信的方式,适用于任意组件间通信 消息订阅与发布 1.订阅消息∶消息名 2.发布消息︰消息内容 消息订阅与发布的工作流程: (A是订阅者,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调度的任务有可能有那些类型 总结 为什么需要工作流调度系统 一个完整的大数据分析系统,必然由很多任务单…...
自学黑客(网络安全)必学内容
随着时代的发展,经济、社会、生产、生活越来越依赖网络。而随着万物互联的物联网技术的兴起,线上线下已经打通,虚拟世界和现实世界的边界正变得模糊。这使得来自网络空间的攻击能够穿透虚拟世界的边界,直接影响现实世界的安全。 …...
Java每日一练(20230518) 移除元素、跳跃游戏II、复原IP地址
目录 1. 移除链表元素 🌟 2. 跳跃游戏 II 🌟🌟 3. 复原 IP 地址 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 移…...
diff命令和vimdiff命令
文章目录 diff命令基本用法选项示例 vimdiff命令命令格式选项说明常用操作 diff命令 diff命令是一个文本比较工具,用于比较两个文件的内容,它会逐行比较两个文件的内容并输出它们之间的差异。下面是diff命令的常用选项和用法: 基本用法 比…...
AcWing 797.差分(C++)
目录 1.题目描述 2.AC 1.题目描述 797.差分 输入一个长度为 nn 的整数序列。 接下来输入 mm 个操作,每个操作包含三个整数 l,r,cl,r,c,表示将序列中 [l,r][l,r] 之间的每个数加上 cc。 请你输出进行完所有操作后的序列。 输入格式 第一行包含两…...
Python每日一练(20230515) 只出现一次的数字 I\II\III
目录 1. 只出现一次的数字 Single Number 2. 只出现一次的数字 II Single Number II 3. 只出现一次的数字 III Single Number III 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 leetcod…...
基于【EasyDL】【图像分类】实现农作物病害识别小程序
内容、数据集来源:基于飞桨的农作物病害智能识别系统 - 飞桨AI Studio 项目背景 联合国粮食及农业组织的一份报告表明,每年农业生产的自然损失中有三分之一以上是由农业病虫害造成的,使这些成为当前影响农业生产和农业生产的最重要因素。需要考虑的农业…...
元宇宙又“死”了!Epic老板:你当6亿用户是摆设?
“扎克伯格花了数年时间试图让Metaverse成为现实,但现在它已被AI取代,并走向科技创意的坟墓。”一篇表达“元宇宙已死”的文章近期在推特上引发热议,而游戏制作公司Epic Games CEO Tim Sweeney的还击更是让这个话题热上加热。 “搞一次在线守…...
阶段小结2022
工作马上一年,对于一年工作能力提升可能逐步在提升,业务能力也在慢慢提升,虽然没有一年前想象的飞起状态,但是刚接触这一行,希望越来越好。 之前每次的遇到的问题其实都会在笔记或者博客中记录,但是没有整体…...
linux0.12-8-11-vsprintf.c
[383页] 1、 这一小节可以不看代码如何实现,因为标准的C库函数; 2、 等自己看完的这本书,有兴趣过来研究研究也是可以的。 8-11 vsprintf.c程序 8-11-1 功能描述 该程序主要包括vsprintf(),用于对参数产生格式化的输出。由于该函数是C函数…...
Node.js 与 WebAssembly
目录 1、简介 2、关键概念 3、生成WebAssembly模块 4、如何使用它 5、与操作系统交互 1、简介 首先,让我们了解为什么WebAssembly是一个很棒的工具,并学会自己使用它。 WebAssembly是一种类似汇编的高性能语言,可以从各种语言编译&…...
OpenCL编程指南-4.4矢量操作符
矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符(加()、减(–)、乘(*)和除(/)),可以作用于内置整数、浮点标量和矢量数…...
Godot PCK解包原理与专业逆向实践指南
1. 这不是“解压软件”,而是Godot游戏逆向工程的第一把手术刀你刚下载了一款用Godot引擎开发的独立游戏,想研究它的UI动效逻辑,或者复刻一段粒子特效,又或者只是单纯好奇——那个让你反复通关三次的像素风过场动画,图层…...
无机布防火卷帘门价格怎么算?按尺寸定制,按需报价
无机布防火卷帘门作为建筑防火分区的核心设备,价格一直是工程采购的关注重点。很多用户在询价时,会发现不同厂家的报价差异较大,这是因为无机布防火卷帘门的价格并非按统一单价计算,而是完全根据项目的实际需求定制化核算。 &…...
DeepSeek代码质量评估实战手册:7步完成从混沌到可度量的质变跃迁
更多请点击: https://kaifayun.com 第一章:DeepSeek代码质量评估的底层逻辑与核心价值 DeepSeek代码质量评估并非简单地统计行数或检测语法错误,而是基于多维语义理解构建的推理系统。其底层逻辑融合了静态分析、符号执行与大语言模型生成式…...
保姆级教程:在ROS2 Humble/Foxy的Gazebo中配置RGB-D相机(附解决点云颜色/坐标问题)
ROS2 Humble/Foxy中Gazebo深度相机仿真全攻略:从配置到点云问题解决在机器人仿真开发中,深度相机(RGB-D)是不可或缺的传感器之一。它能够同时提供彩色图像和深度信息,为SLAM、物体识别、避障等任务提供关键数据支持。本…...
浅聊26上半年软考架构师
2026年上半年架构师考试已然落幕,大家都考的如何?架构师共有三门考试,上午综合知识(75道选择题)案例分析,时间为8.30-12.30;下午论文,时间为14.30-16.30。下面说说我整体的备考过程。…...
Redis沙盒体验:在浏览器中零门槛掌握NoSQL核心技能
Redis沙盒体验:在浏览器中零门槛掌握NoSQL核心技能 【免费下载链接】try.redis A demonstration of the Redis database. 项目地址: https://gitcode.com/gh_mirrors/tr/try.redis 当你第一次听说Redis时,是否被那些晦涩的技术术语吓退࿱…...
Office RibbonX Editor:让Office界面定制变得像搭积木一样简单
Office RibbonX Editor:让Office界面定制变得像搭积木一样简单 【免费下载链接】office-ribbonx-editor An overhauled fork of the original Custom UI Editor for Microsoft Office, built with WPF 项目地址: https://gitcode.com/gh_mirrors/of/office-ribbon…...
微信小程序3D开发框架技术对比:XR-Frame与threejs-miniprogram
随着微信小程序逐步支持3D渲染与AR能力,开发者面临两个主要官方方案:自研的XR-Frame和适配Three.js的threejs-miniprogram。本文将从架构设计、渲染机制、功能集成、开发模式及适用场景等维度进行技术分析,为技术选型提供参考。一、XR-Frame&…...
双系统Ubuntu磁盘告急?别重装!用GParted无损扩容保姆级教程(附U盘启动盘制作)
双系统Ubuntu磁盘告急?别重装!用GParted无损扩容保姆级教程(附U盘启动盘制作)当你在Windows和Ubuntu双系统环境下工作时,是否遇到过这样的窘境:当初安装时给Ubuntu分配的空间捉襟见肘,而Windows…...
Unity iOS构建报错SDK version is 0的根因与精准修复
1. 这个报错不是Unity在“发脾气”,而是工程配置在“装死”刚接手一个老项目,打开Unity编辑器,点Build Settings准备打包iOS,结果弹出一行红字:“SDK version is 0, cannot build”。我第一反应是——这什么鬼…...
