Activiti源码跟踪之Task表单操作GetTaskFormCmd

来源:互联网 发布:axure iphone组件 mac 编辑:程序博客网 时间:2024/04/29 21:10

在Activiti中总共有三种表单,动态表单,普通表单和外置表单。本文介绍的是动态表单。

FormService.getTaskFormCmd:查询Task表单。通过源码跟踪,查看如何获取Task表单


一、FormProperty

Task可以配置属性值,比如有一个审核的任务,对应的流程定义XML代码如下:


<userTask id="audit" name="审核">      <extensionElements>        <activiti:formProperty id="vendorCode" name="供应商" type="string" expression="1" variable="1" readable="false" required="true"/>        <activiti:formProperty id="date" name="时间" type="date" datePattern="MM-dd-yyyy hh:mm"/>        <activiti:formProperty id="amount" name="总数" type="long" writable="false" required="true"/>        <activiti:formProperty id="is_vip" name="是否会员" type="boolean" writable="false"/>        <activiti:formProperty id="approved" name="是否通过" type="enum" required="true">          <activiti:value id="1" name="通过"/>          <activiti:value id="2" name="驳回"/>        </activiti:formProperty>      </extensionElements>    </userTask>

其中activiti:formProperty用来定义Task的属性:

public interface FormProperty extends Serializable {    /** 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();    /** Type of the property. */  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();}

支持的表单属性有以下几种:

  • 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)


二、如何去获取在流程定义中定义的表单内容?

TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId);

GetTaskFormCmd的execute方法:

public TaskFormData execute(CommandContext commandContext) {    TaskEntity task = commandContext      .getTaskEntityManager()      .findTaskById(taskId);    if (task == null) {      throw new ActivitiObjectNotFoundException("No task found for taskId '" + taskId +"'", Task.class);    }        if(task.getTaskDefinition() != null) {      TaskFormHandler taskFormHandler = task.getTaskDefinition().getTaskFormHandler();      if (taskFormHandler == null) {        throw new ActivitiException("No taskFormHandler specified for task '" + taskId +"'");      }            return taskFormHandler.createTaskForm(task);    } else {      // Standalone task, no TaskFormData available      return null;    }  }

核心代码再第9行task.getTaskDefinition()获取Task属性

public TaskDefinition getTaskDefinition() {    if (taskDefinition==null && taskDefinitionKey!=null) {      ProcessDefinitionEntity processDefinition = Context        .getProcessEngineConfiguration()        .getDeploymentManager()        .findDeployedProcessDefinitionById(processDefinitionId);      taskDefinition = processDefinition.getTaskDefinitions().get(taskDefinitionKey);    }    return taskDefinition;  }

第6行代码findDeployedProcessDefinitionById,根据processDefinitionId查询流程定义:

public ProcessDefinitionEntity findDeployedProcessDefinitionById(String processDefinitionId) {    if (processDefinitionId == null) {      throw new ActivitiIllegalArgumentException("Invalid process definition id : null");    }        // first try the cache    ProcessDefinitionEntity processDefinition = processDefinitionCache.get(processDefinitionId);        if (processDefinition == null) {      processDefinition = Context.getCommandContext()        .getProcessDefinitionEntityManager()        .findProcessDefinitionById(processDefinitionId);      if (processDefinition == null) {        throw new ActivitiObjectNotFoundException("no deployed process definition found with id '" + processDefinitionId + "'", ProcessDefinition.class);      }      processDefinition = resolveProcessDefinition(processDefinition);    }    return processDefinition;  }

第7行代码变量processDefinitionCache是一个DeploymentCache实例对象,在这里引申一下。

当初始化流程引擎的时候,会执行下面的方法

org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl


buildProcessEngine()--->init()--->initDeployers(),这时候processDefinitionCache会被初始化。那么processDefinitionCache什么时候赋值的呢?processDefinitionCache属于DeploymentCache对象,可以看出应该是在流程部署的时候进行赋值的。可以参考:Activiti源码跟踪之流程部署


接着往下看--》resolveProcessDefinition方法

public ProcessDefinitionEntity resolveProcessDefinition(ProcessDefinitionEntity processDefinition) {    String processDefinitionId = processDefinition.getId();    String deploymentId = processDefinition.getDeploymentId();    processDefinition = processDefinitionCache.get(processDefinitionId);    if (processDefinition==null) {      DeploymentEntity deployment = Context        .getCommandContext()        .getDeploymentEntityManager()        .findDeploymentById(deploymentId);      deployment.setNew(false);      deploy(deployment, null);      processDefinition = processDefinitionCache.get(processDefinitionId);            if (processDefinition==null) {        throw new ActivitiException("deployment '"+deploymentId+"' didn't put process definition '"+processDefinitionId+"' in the cache");      }    }    return processDefinition;  }

如果processDefinitionCache没有流程定义的话,重新部署流程:

      deployment.setNew(false);      deploy(deployment, null);

因为部署会把流程定义放在缓存中,所以这个时候再去processDefinitionCache查询流程定义。

根据taskDefinitionKey就可以获取到TaskDefinition


三、如何解析TaskDefinition()

再看下GetTaskFormCmd的execute方法

TaskFormHandler taskFormHandler = task.getTaskDefinition().getTaskFormHandler();taskFormHandler.createTaskForm(task);

DefaultTaskFormHandler.createTaskForm--->DefaultFormHandler.initializeFormProperties(taskFormData, task.getExecution())。循环DefaultFormHandler的formPropertyHandlers获取到FormProperty。


四:扩展:如何根据ProcessDefinitionId和TaskDefinitionKey获取到表单属性

1、根据processDefinitionId查询流程定义

ProcessDefinitionEntity processDefinition = Context.getProcessEngineConfiguration().getDeploymentManager()                .findDeployedProcessDefinitionById(processDefinitionId);

2、根据TaskDefinitionKey获取Task定义

TaskDefinition taskDefinition = processDefinition.getTaskDefinitions().get(taskDefinitionKey);

3、获取Task表单属性

因为DefaultTaskFormHandler有FormPropertyHandlers属性,所以可以直接从DefaultTaskFormHandler获取FormPropertyHandlers

DefaultTaskFormHandler taskFormHandler = (DefaultTaskFormHandler) taskDefinition.getTaskFormHandler();

public class FormPropertyHandler implements Serializable {  private static final long serialVersionUID = 1L;    protected String id;  protected String name;  protected AbstractFormType type;  protected boolean isReadable;  protected boolean isWritable;  protected boolean isRequired;  protected String variableName;  protected Expression variableExpression;  protected Expression defaultExpression;    ......}

然后获取表单属性:

formPropertyHandler.getId();formPropertyHandler.getName();formPropertyHandler.getType().getName()