赞
踩
流程实例按步骤执行时,需要保存并使用一些数据,在Flowable中,这些数据称为变量(variable)。
流程实例可以持有变量,称作流程变量(process variables)。
为了使用效率,Flowable将变量分为两种:运行时变量、历史变量。
流程实例运行时的变量,存入act_ru_variable表中。在流程实例运行结束时,此实例的变量在表中删除。
在流程实例创建及启动时,可设置流程变量。所有的startProcessInstanceXXX方法都有一个可选参数用于设置变量。例如,在RuntimeService中:
ProcessInstance startProcessInstanceByKey(String processDefinitionKey, Map<String, Object> variables);
也可以在流程执行中加入变量。例如,(RuntimeService):
void setVariable(String executionId, String variableName, Object value);
void setVariableLocal(String executionId, String variableName, Object value);
void setVariables(String executionId, Map<String, ? extends Object> variables);
void setVariablesLocal(String executionId, Map<String, ? extends Object> variables);
读取变量方法(请注意TaskService中有类似的方法。这意味着任务与执行一样,可以持有局部变量,其生存期为任务持续的时间。)
Map<String, Object> getVariables(String executionId);
Map<String, Object> getVariablesLocal(String executionId);
Map<String, Object> getVariables(String executionId, Collection<String> variableNames);
Map<String, Object> getVariablesLocal(String executionId, Collection<String> variableNames);
Object getVariable(String executionId, String variableName);
<T> T getVariable(String executionId, String variableName, Class<T> variableClass);
注意:由于流程实例结束时,对应在运行时表的数据跟着被删除。所以,查询一个已经完结流程实例的变量,只能在历史变量表中查找。
历史变量,存入act_hi_varinst表中。在流程启动时,流程变量会同时存入历史变量表中;在流程结束时,历史表中的变量仍然存在。可理解为“永久代”的流程变量。
获取已完成的、id为’XXX’的流程实例中,所有的HistoricVariableInstances(历史变量实例),并以变量名排序。
historyService.createHistoricVariableInstanceQuery()
.processInstanceId("XXX")
.orderByVariableName.desc()
.list();
在实际业务中,流程伴随着各种各样的表单,Flowable引擎将表单数据统一作为流程变量存入变量表中。所以,对于Flowable引擎,可以完全独立于表单运行,因为可以用流程变量替代表单数据。
但一般的,我们需要结构化的数据,表单仍然是我们推荐的用法。
表单定义有两种方法,内置表单和外部表单。
以请假为例,XML内容:
<process id="leave" name="请假流程-内置表单"> <startEvent id="start"> <extensionElements> <flowable:formProperty id="startDate" name="请假开始事件" type="date" datePattern="dd-MMM-yyyy" required="true" readable="true" writeable="true"/> <flowable:formProperty id="endDate" name="请假结束事件" type="date" datePattern="dd-MMM-yyyy" required="true" readable="true" writeable="true"/> <flowable:formProperty id="reason" name="请假原因" type="string" required="true" readable="true" writeable="true"/> <flowable:formProperty id="leaveType" type="enum" name="请假类型"> <flowable:value id="personalLeave" name="事假" /> <flowable:value id="annualLeave" name="年假" /> </flowable:formProperty> </extensionElements> </startEvent> </process>
使用方法:
StartFormData FormService.getStartFormData(String processDefinitionId)
或
TaskFormData FormService.getTaskFormData(String taskId)
内置表单了解即可,实际应用更多的是使用外部表单。
根据表单文件自行渲染的任务表单,称为外部表单。
<process id="leave" name="请假流程-内置表单">
<startEvent id="start" flowable:formKey="form1"></startEvent>
</process>
注意:*flowable:formKey=“form1”*中的"form1"对应表单定义文件的"key"值。
{ "key": "form1", "name": "My first form", "fields": [ { "id": "input1", "name": "Input1", "type": "text", "required": false, "placeholder": "empty" } ], "outcomes": [ { "id": "null", "name": "Accept" }, { "id": "null", "name": "Reject" } ] }
在springboot环境下,resources/forms目录下任何.form后缀的表单定义文件都会被自动部署。
例如,将2.2.2表单定义内容保存为leave.form文件,放入resources/forms目录下。
注意:实际应用中,应当让前端流程设计器生成指定格式的表单定义文件,通过与前文提到的接口方式,更新部署流程定义及表单定义资源。
实际上,渲染表单所需的所有数据都组装在下面两个方法:
StartFormData FormService.getStartFormData(String processDefinitionId)
TaskFormdata FormService.getTaskFormData(String taskId)
可以通过下面两个方法提交表单参数:
ProcessInstance FormService.submitStartFormData(String processDefinitionId, Map<String,String> properties)
void FormService.submitTaskFormData(String taskId, Map<String,String> properties)
表单参数FormProperty的具体信息:
public interface FormProperty { /** * 在{@link FormService#submitStartFormData(String, java.util.Map)} * 或{@link FormService#submitTaskFormData(String, java.util.Map)} * 中提交参数时使用的key */ String getId(); /** 显示标签 */ String getName(); /** 在本接口中定义的类型,例如{@link #TYPE_STRING} */ FormType getType(); /** 可选。这个参数需要显示的值 */ String getValue(); /** 这个参数是否可以读取:在表单中显示,并可通过 * {@link FormService#getStartFormData(String)} * 与{@link FormService#getTaskFormData(String)} * 方法访问。 */ boolean isReadable(); /** 用户提交表单时是否可以包含这个参数? */ boolean isWritable(); /** 输入框中是否必填这个参数 */ boolean isRequired(); }
获取指定流程实例的表单数据的方法:
FormModel RuntimeService.getStartFormModel(String processDefinitionId, String processInstanceId);
提交表单数据的方法:
// 附带表单数据启动流程实例
ProcessInstance RuntimeService.startProcessInstanceWithForm(String processDefinitionId, String outcome, Map<String,Object> properties, String taskName);
// 附带表单数据完成任务
void TaskService.completeTaskWithForm(String taskId, String formDefinitionId, String outcome, Map<String,Object> properties);
表单数据实际存放在流程变量表,所以,用流程变量的方法同样可以获取及提交表单数据。
表单支持以下类型字段
在实际应用中,Flowable提供的表单字段类型并不能完全满足需求,往往我们需要自定义表单字段类型。
所有自定义字段类型需要继承一个表达类型抽象类“org.flowable.engine.form.AbstractFormType”。
比如,定义一个"卡片"自定义类型:
public class CardFormType extends AbstractFormType { // 定义表单类型的标识符 @Override public String getName() { return "card"; } // 把表单中的值转换为实际的对象(实际处理逻辑根据具体业务而定) @Override public Object convertFormValueToModelValue(String propertyValue) { return propertyValue; } // 把实际对象的值转换为表单中的值(实际处理逻辑根据具体业务而定) @Override public String convertModelValueToFormValue(Object modelValue) { return (String) modelValue; } }
新建配置类,注册自定义字段类型解析类
@Configuration public class ApplicationConfig extends WebMvcConfigurerAdapter { @Bean public BeanPostProcessor activitiConfigurer() { return new BeanPostProcessor() { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof SpringProcessEngineConfiguration) { List<AbstractFormType> customFormTypes = Arrays.<AbstractFormType>asList(new CardFormType()); ((SpringProcessEngineConfiguration)bean).setCustomFormTypes(customFormTypes); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }; } }
Flowable支持自定义表单引擎以适应各种场景。只需要实现接口org.flowable.engine.impl.form.FormEngine,然后在引擎中注册自定义的表单引擎实现类即可。
public class MyFormEngine implements FormEngine { // 表单引擎的名称 @Override public String getName() { return "MyFormEngine"; } // 实际处理逻辑根据具体业务而定 @Override public Object renderStartForm(StartFormData startFormData) { return "MyStartData"; } // 实际处理逻辑根据具体业务而定 @Override public Object renderTaskForm(TaskFormData taskFormData) { return "MyTaskData"; } }
注册方法与自定义表单字段类型相似,在配置类中加入以下语句:
List<FormEngine> customFormEngines = Arrays.<FormEngine>asList(new MyFormEngine());
((SpringProcessEngineConfiguration)bean).setCustomFormEngines(customFormEngines);
使用方法:
Object FormService.getRenderedStartForm(String processDefinitionId, "myFormEngine");
Object FormService.getRenderedTaskForm(String taskId);
通过本篇,我们了解到了表单和流程变量的具体使用,同样的,在实际业务使用中,还需要不少优化。比如,我们可以在formKey中保存通用的key,通过算法或转换得到实际需要使用的表单模板,在普通屏幕尺寸的Web应用中显示一个表单,在手机等小屏幕中显示另一个表单。还有下一篇将讲到的“集成JPA”,进一步对表单和流程变量的使用做出优化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。