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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 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表单模版
相关文章
|
14天前
|
JavaScript 前端开发 Go
CSS 与 JS 对 DOM 解析和渲染的影响
【10月更文挑战第16天】CSS 和 JS 会在一定程度上影响 DOM 解析和渲染,了解它们之间的相互作用以及采取适当的优化措施是非常重要的。通过合理的布局和加载策略,可以提高网页的性能和用户体验,确保页面能够快速、流畅地呈现给用户。在实际开发中,要根据具体情况进行权衡和调整,以达到最佳的效果。
|
15天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
33 3
|
22天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
82 3
|
29天前
|
Web App开发 IDE 测试技术
自动化测试的利器:Selenium 框架深度解析
【10月更文挑战第2天】在软件开发的海洋中,自动化测试犹如一艘救生艇,让质量保证的过程更加高效与精准。本文将深入探索Selenium这一强大的自动化测试框架,从其架构到实际应用,带领读者领略自动化测试的魅力和力量。通过直观的示例和清晰的步骤,我们将一起学习如何利用Selenium来提升软件测试的效率和覆盖率。
|
25天前
|
JavaScript 前端开发 UED
Vue执行流程及渲染解析
【10月更文挑战第5天】
|
28天前
|
人工智能 缓存 Java
深入解析Spring AI框架:在Java应用中实现智能化交互的关键
【10月更文挑战第12天】Spring AI 是 Spring 框架家族的新成员,旨在满足 Java 应用程序对人工智能集成的需求。它支持自然语言处理、图像识别等多种 AI 技术,并提供与云服务(如 OpenAI、Azure Cognitive Services)及本地模型的无缝集成。通过简单的配置和编码,开发者可轻松实现 AI 功能,同时应对模型切换、数据安全及性能优化等挑战。
|
18天前
|
分布式计算 Java 应用服务中间件
NettyIO框架的深度技术解析与实战
【10月更文挑战第13天】Netty是一个异步事件驱动的网络应用程序框架,由JBOSS提供,现已成为Github上的独立项目。
35 0
|
24天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
58 0
|
24天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
49 0
|
24天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
55 0

热门文章

最新文章

推荐镜像

更多