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矢量操作符
矢量操作符 如下描述了可用于矢量数据类型或矢量和标量数据类型组合的各类操作符。 算术操作符 算术操作符(加()、减(–)、乘(*)和除(/)),可以作用于内置整数、浮点标量和矢量数…...
别再让电机白费电了!手把手教你用MTPA算法在STM32上实现节能控制(附代码)
电机节能控制实战:基于STM32的MTPA算法实现与优化 电机控制系统中的能耗问题一直是工业应用中的痛点。传统控制方法往往忽视了电机内部磁阻转矩的潜力,导致电流利用率低下。本文将带你深入理解MTPA(最大转矩电流比)算法的核心思想…...
论文辅导机构哪家好且靠谱?2026专业参考|正规机构实用梳理
对于科研人、高校学生及青年学者而言,论文写作与发表是学术成长路上的重要课题,无论是学位论文的完成,还是期刊论文的投稿,难免会遭遇选题迷茫、框架混乱、查重不达标、投稿无门等痛点。靠谱的论文辅导机构,能有效梳理…...
5.3 风险模型介入:利用Barra CNE5进行因子纯化
5.3 风险模型介入:利用Barra CNE5进行因子纯化 一、引言:为什么需要“纯净”的Alpha? 在上一节中,我们学会了如何将几十个相关因子合成为少数几个复合因子。但这还不够。当你构建的策略在回测中表现优异时,必须回答一…...
新手避坑指南:匿名飞控与FS-I6X遥控器对码、通道设置全流程(附上位机数据解析)
新手避坑指南:FS-I6X遥控器与匿名飞控深度配置手册 第一次拿起遥控器时,我的手心全是汗——那些密密麻麻的拨杆和按钮仿佛在嘲笑我的无知。直到无人机第三次砸向地面,我才明白遥控器配置不是简单的对码就能解决的事。本文将带你穿越新手最易迷…...
K230开发板避坑指南:RGB灯珠共阳/共阴判断方法与GPIO驱动配置详解
K230开发板RGB灯珠实战手册:从电路原理到驱动安全的完整解决方案 1. 硬件工程师必须掌握的LED基础认知 当你第一次拿到K230开发板时,那颗小巧的RGB灯珠可能看起来微不足道,但正是这个看似简单的元件,往往成为硬件调试路上的第一个…...
从班级成绩单到数据分析:用Python轻松复刻ZZULIOJ 1128题,并拓展更多实用功能
从班级成绩单到数据分析:用Python轻松复刻ZZULIOJ 1128题,并拓展更多实用功能 当班主任把一叠成绩单交到你手上时,那些密密麻麻的数字是否让你感到无从下手?作为班干部或助教,我们常常需要从原始成绩数据中提取有价值的…...
手把手调试RH850G3KH中断控制器:INTC1/INTC2寄存器配置避坑手册
手把手调试RH850G3KH中断控制器:INTC1/INTC2寄存器配置避坑手册 在汽车电子控制单元(ECU)开发中,中断处理的实时性和可靠性直接关系到系统稳定性。RH850G3KH作为Renesas旗舰级车规MCU,其双中断控制器架构(I…...
HTML头部元信息避坑指南:提升页面性能、SEO与用户体验的关键细节
引言: 简要说明<head>区域在HTML文档中的重要性。 概述元信息(<meta>标签、<title>、<link>等)对页面渲染、搜索引擎优化(SEO)、社交媒体分享、用户体验和可访问性的影响。 点明本文目的:列举常见误区、错误用法及其解决方案。 一、 基础概念与必备…...
若依框架前后端分离版——高效数据导入实战指南
1. 为什么需要高效数据导入功能 在企业级应用开发中,数据导入是个高频需求场景。想象一下学校每学期要导入上万名学生信息,或者电商平台要批量上架商品,如果一条条手动录入,不仅效率低下还容易出错。我在实际项目中就遇到过这样的…...
Helpy Docker容器化部署最佳实践:快速稳定的生产环境搭建
Helpy Docker容器化部署最佳实践:快速稳定的生产环境搭建 【免费下载链接】helpy Helpy is a modern, open source helpdesk customer support application. Features include knowledgebase, community discussions and support tickets integrated with email. …...
