camunda框架学习(十四)表单系列

一、表单生命周期、定义方式

在这里插入图片描述
在这里插入图片描述
表单使用两种方式
在这里插入图片描述
FormService
在这里插入图片描述
表单定义支持的节点:
在这里插入图片描述

二、外置表单

在这里插入图片描述

    <bpmn:startEvent id="StartEvent_1" camunda:formKey="start.html">
      <bpmn:outgoing>Flow_0ycrxbl</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_0ycrxbl" sourceRef="StartEvent_1" targetRef="Activity_0dhhxgy" />
    <bpmn:userTask id="Activity_0dhhxgy" name="请假申请" camunda:formKey="1.html">
      <bpmn:incoming>Flow_0ycrxbl</bpmn:incoming>
      <bpmn:outgoing>Flow_0b9puvz</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0b9puvz" sourceRef="Activity_0dhhxgy" targetRef="Activity_1c6jr4q" />
    <bpmn:userTask id="Activity_1c6jr4q" name="【总经理】审批" camunda:formKey="2.html">

start.html

开始节点

${startUserId} 发起了 ${category} 类型的流程

1.html

第一个任务节点,【请假申请】

${startUserId} 提交了 ${category} 类型的流程

2.html:

第二个任务节点,【总经理审批】

${startUserId} 提交了 ${category} 类型的流程
    @Test
    public void createDeployment() {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
        Deployment deployment = deploymentBuilder
                .name("外置表单测试")
                .source("本地测试")
                .tenantId("a")
                .addClasspathResource("com.demo/ch18/form.bpmn")
                .addClasspathResource("com.demo/ch18/start.html")
                .addClasspathResource("com.demo/ch18/1.html")
                .addClasspathResource("com.demo/ch18/2.html")
                .deploy();

        System.out.println(deploymentBuilder);
        System.out.println(deployment);
    }

查询启动节点的key

    @Test
    public void getStartFormKey() {
        String processDefinitionId="form:1:5106";
        String startFormKey = formService.getStartFormKey(processDefinitionId);
        System.out.println(startFormKey);
    }

查询任务节点的Key

    @Test
    public void getTaskFormKey() {
        String processDefinitionId = "form:1:5106";
        String taskDefinitionKey = "Activity_0dhhxgy";
        String startFormKey = formService.getTaskFormKey(processDefinitionId, taskDefinitionKey);
        System.out.println(startFormKey);
    }

    @Test
    public void getTaskFormKey2() {
        String processDefinitionId = "form:1:5106";
        String taskDefinitionKey = "Activity_1c6jr4q";
        String startFormKey = formService.getTaskFormKey(processDefinitionId, taskDefinitionKey);
        System.out.println(startFormKey);
    }

三、外置表单常见问题以及解决

查询节点表单渲染内容信息

    /**
     * select * from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ = ? and NAME_ = ?
     * 5101(String), start.html(String)
     */
    @Test
    public void getRenderedStartForm() {
        String processDefinitionId = "form:1:5106";
        Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId, "juel");
        System.out.println(renderedStartForm);
    }

报错2021-03-10 17:31:21.295 [main] ERROR org.camunda.bpm.engine.context [BaseLogger.java : 156] - ENGINE-16004 Exception while closing command context: Form with formKey 'start.html' does not exist: resourceStream is null

通过查看SQL,start.html可以发现与数据库com.demo/ch18/start.html不一致
在这里插入图片描述
故这里需要改一下名称,重新部署

    <bpmn:startEvent id="StartEvent_1" camunda:formKey="com.demo/ch18/start.html">
      <bpmn:outgoing>Flow_0ycrxbl</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_0ycrxbl" sourceRef="StartEvent_1" targetRef="Activity_0dhhxgy" />
    <bpmn:userTask id="Activity_0dhhxgy" name="请假申请" camunda:formKey="com.demo/ch18/1.html">
      <bpmn:incoming>Flow_0ycrxbl</bpmn:incoming>
      <bpmn:outgoing>Flow_0b9puvz</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0b9puvz" sourceRef="Activity_0dhhxgy" targetRef="Activity_1c6jr4q" />
    <bpmn:userTask id="Activity_1c6jr4q" name="【总经理】审批" camunda:formKey="com.demo/ch18/2.html">
      <bpmn:incoming>Flow_0b9puvz</bpmn:incoming>
      <bpmn:outgoing>Flow_08xz0y7</bpmn:outgoing>
    </bpmn:userTask>

再次查询为空

    @Test
    public void getRenderedStartForm() {
        String processDefinitionId = "form:1:5106";
        Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId, "juel");
        System.out.println(renderedStartForm);
    }

debug跟踪到org.camunda.bpm.engine.impl.form.engine.JuelFormEngine

    protected Object executeScript(String scriptSrc, VariableScope scope) {
        ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
        ScriptFactory scriptFactory = processEngineConfiguration.getScriptFactory();
        ExecutableScript script = scriptFactory.createScriptFromSource("juel", scriptSrc);
        ScriptInvocation invocation = new ScriptInvocation(script, scope);

        try {
            processEngineConfiguration.getDelegateInterceptor().handleInvocation(invocation);
        } catch (RuntimeException var8) {
            throw var8;
        } catch (Exception var9) {
            throw new ProcessEngineException(var9);
        }

        return invocation.getInvocationResult();
    }

在这里插入图片描述

说明了开始节点,不能有表达式变量,故去掉startUserId等变量

start.html

开始节点

重新部署

@Test
public void getRenderedStartForm() {
    String processDefinitionId = "form:3:5306";
    Object renderedStartForm = formService.getRenderedStartForm(processDefinitionId, "juel");
    System.out.println(renderedStartForm);
}

在这里插入图片描述
在这里插入图片描述
org.camunda.bpm.engine.impl.form.engine.JuelFormEngine中有return null
`

    public Object renderStartForm(StartFormData startForm) {
        if (startForm.getFormKey() == null) {
            return null;
        } else {
            String formTemplateString = this.getFormTemplateString(startForm, startForm.getFormKey());
            return this.executeScript(formTemplateString, (VariableScope)null);
        }
    }

四、外置表单StartFormData获取

    @Test
    public void getStartFormData() {
        String processDefinitionId = "form:3:5306";
        StartFormData startFormData = formService.getStartFormData(processDefinitionId);
        System.out.println("############");
        System.out.println(startFormData.getDeploymentId());
        System.out.println(startFormData.getProcessDefinition());
        System.out.println(startFormData.getFormKey());
        List<FormProperty> formProperties = startFormData.getFormProperties();
        System.out.println(formProperties);
        List<FormField> formFields = startFormData.getFormFields();
        System.out.println(formFields);
        System.out.println("############");
    }

在这里插入图片描述

五、外置表单查询渲染内容并提交任务

启动表单实例:
    @Test
    public void submitStartForm() {
        String processDefinitionId = "form:3:5306";
        VariableMap variableMap = Variables.createVariables()
                .putValue("days", 10)
                .putValue("reason", "请假三天")
                .putValue("startUserId", "张三")
                .putValue("category", "年假");
        ProcessInstance processInstance = formService.submitStartForm(processDefinitionId, variableMap);
        System.out.println(processInstance);
    }

startUserIdcategory必须传递,因为1.html2.html中的juel表达式会用到
在这里插入图片描述

获取并渲染任务节点的表单内容:
   @Test
    public void getTaskFormData() {
        Task task = taskService.createTaskQuery().taskId("5411").singleResult();
        System.out.println(task.getId());

        TaskFormData taskFormData = formService.getTaskFormData(task.getId());
        System.out.println("############");
        System.out.println(taskFormData.getDeploymentId());
        System.out.println(taskFormData.getTask());
        System.out.println(taskFormData.getFormKey());
        List<FormProperty> formProperties = taskFormData.getFormProperties();
        System.out.println(formProperties);
        List<FormField> formFields = taskFormData.getFormFields();
        System.out.println(formFields);
        System.out.println("############");
    }

    @Test
    public void getRenderedTaskForm() {
        Object renderedTaskForm = formService.getRenderedTaskForm("5411", "juel");
        System.out.println("############");
        System.out.println(renderedTaskForm);
        System.out.println("############");
    }

在这里插入图片描述

提交任务节点并保存表单:
    @Test
    public void submitTaskForm() {
        VariableMap variableMap = Variables.createVariables()
                .putValue("startUserId", "王五")
                .putValue("category", "年假");

        formService.submitTaskForm("5411", variableMap);
    }

在这里插入图片描述

六、动态表单定义及信息获取

在这里插入图片描述

    <bpmn:startEvent id="StartEvent_1">
      <bpmn:extensionElements>
        <camunda:formData>
          <camunda:formField id="days" label="请假天数" type="long" defaultValue="3">
            <camunda:properties>
              <camunda:property id="aa" value="aa" />
            </camunda:properties>
          </camunda:formField>
          <camunda:formField id="reason" label="请假原因" type="string" />
          <camunda:formField id="start_time" label="请假开始时间" type="date" />
          <camunda:formField id="end_time" label="请假结束时间" type="date" />
          <camunda:formField id="enums" type="enum">
            <camunda:value id="a" name="a" />
            <camunda:value id="b" name="b" />
          </camunda:formField>
        </camunda:formData>
      </bpmn:extensionElements>
      <bpmn:outgoing>Flow_0ycrxbl</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_0ycrxbl" sourceRef="StartEvent_1" targetRef="Activity_0dhhxgy" />
    <bpmn:userTask id="Activity_0dhhxgy" name="请假申请">
      <bpmn:extensionElements>
        <camunda:formData>
          <camunda:formField id="days" label="请假天数" type="long" defaultValue="3" />
          <camunda:formField id="reason" label="请假原因" type="string" />
          <camunda:formField id="start_time" label="请假开始时间" type="date" />
          <camunda:formField id="end_time" label="请假结束时间" type="date" />
          <camunda:formField id="enums" type="enum">
            <camunda:value id="a" name="a" />
            <camunda:value id="b" name="b" />
          </camunda:formField>
        </camunda:formData>
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_0ycrxbl</bpmn:incoming>
      <bpmn:outgoing>Flow_0b9puvz</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0b9puvz" sourceRef="Activity_0dhhxgy" targetRef="Activity_1c6jr4q" />
    <bpmn:userTask id="Activity_1c6jr4q" name="【总经理】审批">
      <bpmn:extensionElements>
        <camunda:formData>
          <camunda:formField id="days" label="请假天数" type="long" defaultValue="3" />
          <camunda:formField id="reason" label="请假原因" type="string" />
          <camunda:formField id="start_time" label="请假开始时间" type="date" />
          <camunda:formField id="end_time" label="请假结束时间" type="date" />
          <camunda:formField id="enums" type="enum">
            <camunda:value id="a" name="a" />
            <camunda:value id="b" name="b" />
          </camunda:formField>
        </camunda:formData>
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_0b9puvz</bpmn:incoming>
      <bpmn:outgoing>Flow_08xz0y7</bpmn:outgoing>
    </bpmn:userTask>
动态表单开始节点字段获取:
 @Test
    public void getStartFormData() {
        String processDefinitionId = "form2:3:5903";
        StartFormData startFormData = formService.getStartFormData(processDefinitionId);

        List<FormField> formFields = startFormData.getFormFields();
        for (FormField formField : formFields) {
            System.out.println("############");
            System.out.println(formField.getId());
            System.out.println(formField.getValue());
            System.out.println(formField.getType());
            System.out.println(formField.getTypeName());
            System.out.println(formField.getLabel());
            System.out.println(formField.getDefaultValue());
            System.out.println("############");
        }

    }
动态表单字段附属获取:
    @Test
    public void getStartFormData2() {
        String processDefinitionId = "form2:4:6003";
        StartFormData startFormData = formService.getStartFormData(processDefinitionId);

        List<FormField> formFields = startFormData.getFormFields();
        for (FormField formField : formFields) {
            System.out.println("############");
           
            FormType formType = formField.getType();
            if (formType instanceof DateFormType) {
                DateFormType dateFormType = (DateFormType) formType;
                Object information = dateFormType.getInformation("datePattern");
                System.out.println("information:" + information);
            }
            if (formType instanceof EnumFormType) {
                EnumFormType enumFormType = (EnumFormType) formType;
                Object information = enumFormType .getInformation("values");
                System.out.println("information:" + information);
            }
            System.out.println("############");
        }

    }

在这里插入图片描述

七、自定义表单引擎思路

formKey及其defaultValue可以使用变量,外置表单内容可以使用变量,再使用juel引擎渲染

org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl

    protected void initFormEngines() {
        if (this.formEngines == null) {
            this.formEngines = new HashMap();
            FormEngine defaultFormEngine = new HtmlFormEngine();
            this.formEngines.put((Object)null, defaultFormEngine);
            this.formEngines.put(defaultFormEngine.getName(), defaultFormEngine);
            FormEngine juelFormEngine = new JuelFormEngine();
            this.formEngines.put(juelFormEngine.getName(), juelFormEngine);
        }

        if (this.customFormEngines != null) {
            Iterator var3 = this.customFormEngines.iterator();

            while(var3.hasNext()) {
                FormEngine formEngine = (FormEngine)var3.next();
                this.formEngines.put(formEngine.getName(), formEngine);
            }
        }

    }

自定义渲染类

public class MyFormEngine implements FormEngine {
    @Override
    public String getName() {
        return null;
    }

    @Override
    public Object renderStartForm(StartFormData startFormData) {
        return null;
    }

    @Override
    public Object renderTaskForm(TaskFormData taskFormData) {
        return null;
    }
}

也可以直接继承JuelFormEngine

public class MyFormEngine extends JuelFormEngine {
    @Override
    public String getName() {
        return "peng";
    }

    @Override
    public Object renderStartForm(StartFormData startFormData) {
        return super.renderStartForm(startFormData);
    }

    @Override
    public Object renderTaskForm(TaskFormData taskFormData) {
        return super.renderTaskForm(taskFormData);
    }
}

    <bean id="processEngineConfiguration"
          class="org.camunda.bpm.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1/camunda"/>
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="123456"/>
        <property name="databaseSchemaUpdate" value="false"/>
        <property name="dbHistoryUsed" value="true"/>

        <!--关闭租户校验-->
        <property name="tenantCheckEnabled" value="false"/>

        <!--自定义表单渲染-->
        <property name="customFormEngines">
            <list>
                <bean class="com.demo.ch18.MyFormEngine"/>
            </list>
        </property>

    </bean>
    @Test
    public void getRenderedStartForm() {
        Object juel = formService.getRenderedTaskForm("6209", "peng");
        System.out.println(juel);
    }

代码参考:https://github.com/zhoupengwa/ProcessEngineDemo

学习来源:腾讯课堂

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值