写点什么

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

发布于: 2021 年 06 月 07 日
工作流框架Activiti中表单的使用!详细解析内置表单和外置表单的渲染方式

Activiti 中的表单

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

  • 对表单的支持有 2 种方式:

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

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

表单属性

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

  • 包含自身的流程变量

  • 通过流程变量的引用

  • Activiti 支持存储复杂的 Java 对象作为流程变量:

  • 序列化对象

  • Jpa 实体对象

  • 整个 XML 文档作为字符串

  • 用户是在启动一个流程和完成用户任务时,与流程进行交互

  • 表单需要某个 UI 技术渲染之后才能够与用户进行交互

  • 为了能够使用不同 UI 技术变得容易,流程定义包含一个对流程变量中复杂的 Java 类型对象到一个 properties Map<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()
复制代码


<br />


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 表单模版

发布于: 2021 年 06 月 07 日阅读数: 102
用户头像

一位攻城狮的自我修养 2021.04.06 加入

分享技术干货,面试题和攻城狮故事。 你的关注支持是我持续进步的最大动力! https://github.com/ChovaVea

评论

发布
暂无评论
工作流框架Activiti中表单的使用!详细解析内置表单和外置表单的渲染方式