工作流Activiti框架中表单的使用!详细解析内置表单和外置表单的渲染

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 本文介绍了工作流Activiti框架中表单的使用。在工作流Activiti框架中,支持在业务流程中添加内置表单和外置表单。详细说明了工作流中的表单需要具备的属性以及表单属性在工作流中的映射关系。最后介绍了工作流Activiti框架中对支持的表单的渲染方式。通过这篇文章,可以帮助我们在工作流Activiti框架中更加熟练地运用表单。

Activiti中的表单

  • Activiti提供了一种方便而且灵活的方式在业务流程中以手工方式添加表单
  • 对表单的支持有2种方式:

    • 通过表单属性对内置表单进行渲染
    • 通过表单属性对外置表单进行渲染

表单属性

  • 业务流程相关联的所有信息:

    • 包含自身的流程变量
    • 通过流程变量的引用
  • Activiti支持存储复杂的Java对象作为流程变量:

    • 序列化对象
    • Jpa实体对象
    • 整个XML文档作为字符串
  • 用户是在启动一个流程和完成用户任务时,与流程进行交互
  • 表单需要某个UI技术渲染之后才能够与用户进行交互
  • 为了能够使用不同UI技术变得容易,流程定义包含一个对流程变量中复杂的Java类型对象到一个propertiesMap<String,String> 类型的转换逻辑
  • 使用Activiti API的方法查看公开的属性信息.然后,任意UI技术都能够在这些属性上面构建一个表单.该属性专门为流程变量提供了一个视图. 表单所需要显示的属性可以返回值FormData中获取:
StartFormData FormService.getStartFormData(String processDefinitionId)

或者

TaskFormdata FormService.getTaskFormData(String taskId)
  • 在默认情况下,内置的表单引擎遇到这些变量就像对待流程变量一样.如果任务表单属性和流程变量是一对一的关系,那么任务表单属性就不需要进行申明了:
<startEvent id="start" />
  • 当执行到开始事件时,所有的流程变量都是可用的,但是
formService.getStartFormData(String processDefinitionId).getFormProperties()

会是一个空值,因为没有定义一个具体的映射

  • 表单中所有被提交的属性都将会作为流程变量被存储在Activiti使用的数据库中. 这意味着在一个表单中新添加一个简单的input输入字段,也会作为一个新的变量被存储
  • 属性来自于流程变量,但是不一定非要作为流程变量存储:

    • 一个流程变量可能是JPA实体如类Address.在某种UI技术中使用的表单属性StreetName可能会关联到一个表达式 #{address.street}
  • 用户提交的表单属性应该作为流程变量进行存储
  • 使用UEL值表达式将其作为流程变量的一个嵌套属性进行存储
  • 提交的表单属性默认的行为是作为流程变量进行存储,除非一个 formProperty 申明了其他的规则
  • 类型转换也可以应用于表单数据和流程变量之间的处理:
<userTask id="task">
  <extensionElements>
    <activiti:formProperty id="room" />
    <activiti:formProperty id="duration" type="long"/>
    <activiti:formProperty id="speaker" variable="SpeakerName" writable="false" />
    <activiti:formProperty id="street" expression="#{address.street}" required="true" />
  </extensionElements>
</userTask>
  • 表单属性room将会被映射为String类型流程变量room
  • 表单属性duration将会被映射为java.lang.Long类型流程变量duration
  • 表单属性speaker将会被映射为流程变量SpeakerName:

    • writable="false" 只能够在TaskFormData对象中使用.如果属性speaker提交,将会抛出一个ActivitiException的异常
    • readable="false" 该属性就会在FormData进行排除,但是在提交后仍然会对其进行处理
  • 表单属性street将会映射为Java Bean address的属性street作为String类型的流程变量:

    • 当提交的表单属性并没有提供并且required="true" 时,那么就会抛出一个异常
  • 表单数据也可以作为FormData的一部分提供类型元数据.该FormData可以从以下方法的返回值中获取:
StartFormData FormService.getStartFormData(String processDefinitionId)
TaskFormdata FormService.getTaskFormData(String taskId)
  • 表单属性类型:

    • string: org.activiti.engine.impl.form.StringFormType
    • long: org.activiti.engine.impl.form.LongFormType
    • enum: org.activiti.engine.impl.form.EnumFormType
    • date: org.activiti.engine.impl.form.DateFormType
    • boolean: org.activiti.engine.impl.form.BooleanFormType
  • 对于声明每一个表单属性,FormProperty信息可以通过以下方式获取:
List<FormProperty> formService.getStartFormData(String processDefinitionId).getFormProperties()

或者

List<FormProperty> formService.getTaskFormData(String taskId).getFormProperties()


public interface FormProperty {
  /**

  the key used to submit the property in {@link FormService#submitStartFormData(String, java.util.Map)}
   * or {@link FormService#submitTaskFormData(String, java.util.Map)} */
  String getId();
  /** the display label */
  String getName();
  /** one of the types defined in this interface like e.g. {@link #TYPE_STRING} */
  FormType getType();
  /** optional value that should be used to display in this property */
  String getValue();
  /** is this property read to be displayed in the form and made accessible with the methods
   * {@link FormService#getStartFormData(String)} and {@link FormService#getTaskFormData(String)}. */
  boolean isReadable();
  /** is this property expected when a user submits the form? */
  boolean isWritable();
  /** is this property a required input field */
  boolean isRequired();
}
  • 示例:
<startEvent id="start">
  <extensionElements>
    <activiti:formProperty id="speaker"
      name="Speaker"
      variable="SpeakerName"
      type="string" />

    <activiti:formProperty id="start"
      type="date"
      datePattern="dd-MMM-yyyy" />

    <activiti:formProperty id="direction" type="enum">
      <activiti:value id="left" name="Go Left" />
      <activiti:value id="right" name="Go Right" />
      <activiti:value id="up" name="Go Up" />
      <activiti:value id="down" name="Go Down" />
    </activiti:formProperty>

  </extensionElements>
</startEvent>
  • 所有的表单属性的信息都是可以通过API进行访问的:

    • formProperty.getType().getName(): 获取类型的名称
    • formProperty.getType().getInformation("datePattern"): 获取日期的匹配方式
    • formProperty.getType().getInformation("values"): 可以获取到枚举值
  • Activiti控制台支持表单属性并且可以根据表单定义对表单进行渲染:
<startEvent ... >
  <extensionElements>
    <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
    <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
    <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
  </extensionElements>
</userTask>

当使用Activiti控制台时,会被渲染成流程的启动表单

外置表单的渲染

  • Activiti中的API允许执行Activiti流程引擎之外的方式渲染任务表单,可以用自定义方式对任务表单进行渲染
  • 所有需要渲染的表单属性进行装配的服务方法有两种:

    • StartFormData FormService.getStartFormData(String processDefinitionId)
    • TaskFormdata FormService.getTaskFormData(String taskId)
  • 表单属性提交的两种方式:

    • ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)
    • void FormService.submitStartFormData(String taskId, Map<String,String> properties)
  • 可以将任何表单模版资源放进要部署的业务文档之中(如果想要按照流程的版本进行存储).将会在部署中作为一种可用的资源
  • 获取部署表单模版的方式有两种:

    • String ProcessDefinition.getDeploymentId()
    • InputStream RepositoryService.getResourceAsStream(String deploymentId, String resourceName)
    • 这样就可以获取表单模版定义文件,就可以在应用中渲染或者显示表单
  • 也可以使用该功能获取任务表单之外的其他的部署资源用于其他的目的
  • 属性 <userTask activiti:formKey="..." 暴露方式API:

    • String FormService.getStartFormData(String processDefinitionId).getFormKey()
    • String FormService.getTaskFormData(String taskId).getFormKey()
  • 可以使用这个存储部署的模版中的全名(例如org/activiti/example/form/my-custom-form.xml) 但是这并不是必须的:

    • 可以在表单属性中存储一个通用的key,然后运用一种算法或者换转去得到你实际使用的模版
    • 当需要通过不同UI技术渲染不同的表单会更加方便:

      • 使用正常屏幕大小的web应用程序的表单
      • 移动手机小屏幕的表单
      • IM表单
      • email表单模版
相关文章
|
26天前
|
小程序 前端开发 关系型数据库
uniapp跨平台框架,陪玩系统并发性能测试,小程序源码搭建开发解析
多功能一体游戏陪练、语音陪玩系统的开发涉及前期准备、技术选型、系统设计与开发及测试优化。首先,通过目标用户分析和竞品分析明确功能需求,如注册登录、预约匹配、实时语音等。技术选型上,前端采用Uni-app支持多端开发,后端选用PHP框架确保稳定性能,数据库使用MySQL保证数据一致性。系统设计阶段注重UI/UX设计和前后端开发,集成WebSocket实现语音聊天。最后,通过功能、性能和用户体验测试,确保系统的稳定性和用户满意度。
|
26天前
|
机器学习/深度学习 人工智能 自然语言处理
深度解析Recraft V3:突破文本渲染限制,文生图黑马是怎样炼成的?
Recraft V3模型在文本生成图像(Text-to-Image)领域取得重大突破,通过创新的&quot;Bridging Text Spotting&quot;方法,解决了传统方法中误差累积和性能不佳的问题。该模型采用独立训练的检测器和识别器,并引入Bridge和Adapter机制,确保高质量图像生成。Recraft V3在多个数据集上表现优异,如Total-Text准确率达83.3%,ICDAR 2015达89.5%。其应用前景广泛,涵盖广告设计、教育和娱乐等领域,为文生图技术的实际应用提供了新可能。
92 27
|
2月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
3月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
3月前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
49 0
|
4月前
|
JavaScript 前端开发 Go
CSS 与 JS 对 DOM 解析和渲染的影响
【10月更文挑战第16天】CSS 和 JS 会在一定程度上影响 DOM 解析和渲染,了解它们之间的相互作用以及采取适当的优化措施是非常重要的。通过合理的布局和加载策略,可以提高网页的性能和用户体验,确保页面能够快速、流畅地呈现给用户。在实际开发中,要根据具体情况进行权衡和调整,以达到最佳的效果。
|
4月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
62 3
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
53 0
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

推荐镜像

更多