flowable表單引擎

flowable表單引擎作為一個(gè)獨(dú)立的模塊辆雾,也包括表單定義,部署等過程月劈。

1. API及與流程引擎的結(jié)合

如下圖所示度迂,表單引擎也有一個(gè)獨(dú)立的配置文件,配置類猜揪,配置引擎及三個(gè)Service.



在實(shí)際使用中我們也是將其配置嵌入到流程引擎的配置中惭墓,配置形式如下(省略了非相關(guān)配置):

    <bean id="processEngineConfiguration"
          class="org.flowable.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="asyncExecutorActivate" value="false" />
        <property name="configurators">
            <list>
                <bean class="org.flowable.form.engine.configurator.FormEngineConfigurator">
                    <property name="formEngineConfiguration">
                        <bean class="org.flowable.form.engine.impl.cfg.StandaloneFormEngineConfiguration">
                            <property name="dataSource" ref="dataSource"/>
                            <property name="databaseSchemaUpdate" value="true"/>
                        </bean>
                    </property>
                </bean>
            </list>
        </property>
    </bean>


    <bean id="formRepositoryService" factory-bean="processEngine" factory-method="getFormEngineRepositoryService" />

在應(yīng)用重啟時(shí)數(shù)據(jù)庫中會(huì)增加act_fo_為前綴的六張數(shù)據(jù)庫表格:
act_fo_databasechangelog: Liquibase用來跟蹤數(shù)據(jù)庫變量的
act_fo_databasechangeloglock: Liquibase用來保證同一時(shí)刻只有一個(gè)Liquibase實(shí)例在運(yùn)行
act_fo_form_definition:存儲(chǔ)表單定義的信息
act_fo_form_instance:存儲(chǔ)用戶填充后表單實(shí)例信息
act_fo_form_deployment:存儲(chǔ)表單部署元數(shù)據(jù)
act_fo_form_resource:存儲(chǔ)表單定義的資源

2. 表單的定義

表單定義文件是以.form為后綴, 內(nèi)容格式為Json格式而姐。如下示例所示腊凶。

{
    "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"
        }
    ]
}

該文件的key屬性是其唯一性標(biāo)識(shí),表單引擎可以通過該key獲取到它毅人, 同時(shí)數(shù)據(jù)庫對(duì)相同key會(huì)維護(hù)不同的版本吭狡。第二部分是表單字段數(shù)組,第三部分是表單結(jié)果丈莺。每一個(gè)表單字段都有id,name和type屬性划煮。id屬性在同一個(gè)表單定義文件中必須唯一,當(dāng)用戶賦值時(shí)它會(huì)作為變量的名稱缔俄,在上例中弛秋,也就是會(huì)創(chuàng)建名稱為input1的變量,值由用戶填入俐载。同時(shí)表單結(jié)果也會(huì)以form_<form-identifier>_outcome獲取得到蟹略,對(duì)于上例,用戶選擇的結(jié)果會(huì)賦值給form_form1_outcome遏佣, 我們可以通過${form_form1_outcome == "Accept"}表達(dá)式來驗(yàn)證表單結(jié)果是否為Accept挖炬。
表單字段的type屬性支持text, multi-line-text,integer,boolean,date等多種類型。

3. 表單的使用

首先在src/main/resources文件夾下創(chuàng)建test.form表單定義文件状婶,內(nèi)容如下:

{
"key": "form1",
"name": "請(qǐng)假流程",
"fields": [
            {
            "id": "startTime",
            "name": "開始時(shí)間",
            "type": "date",
            "required": true,
            "placeholder": "empty"

            },
            {
            "id": "endTime",
            "name": "結(jié)束時(shí)間",
            "type": "date",
            "required": true,
            "placeholder": "empty"
            },
            {
            "id": "reason",
            "name": "請(qǐng)假原因",
            "type": "text",
            "required": true,
            "placeholder": "empty"
            }
    ]
}

然后創(chuàng)建test-form.bpmn20.xml流程定義文件:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
             xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
             xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"
             xmlns:flowable="http://flowable.org/bpmn"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://www.flowable.org/processdef">

    <process id="holidayRequest" name="Holiday Request" isExecutable="true">

        <startEvent id="startEvent" flowable:formKey="form1"/>
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <userTask id="approveTask" name="Approve or reject request" flowable:formKey="form1" flowable:candidateGroups="managers"/>
        <sequenceFlow sourceRef="approveTask" targetRef="holidayApprovedTask"/>

        <userTask id="holidayApprovedTask" name="Holiday approved" flowable:formKey="form1" flowable:assignee="employee"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <endEvent id="approveEnd"/>

    </process>

</definitions>

上面的開始事件和兩個(gè)用戶任務(wù)都帶有flowable:formKey屬性意敛。
然后就可以創(chuàng)建測(cè)試類了,注意用runtimeService.startProcessInstanceWithForm方法啟動(dòng)帶表單的流程膛虫,runtimeService.getStartFormModel查詢流程啟動(dòng)時(shí)的表單信息; taskService.completeTaskWithForm填充表單完成任務(wù)草姻,taskService.getTaskFormModel查詢?nèi)蝿?wù)表單信息。具體測(cè)試類代碼如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class FormTest {
    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private FormRepositoryService formRepositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    /**
     * 流程以及表單的部署
     */
    @Test
    public void deployTest(){
        Deployment deployment = repositoryService.createDeployment()
                .name("表單流程")
                .addClasspathResource("flowable/test-form.bpmn20.xml")
                .deploy();

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().
                deploymentId(deployment.getId())
                .singleResult();
        String processDefinitionId = processDefinition.getId();
        FormDeployment formDeployment = formRepositoryService.createDeployment()
                .name("definition-one")
                .addClasspathResource("flowable/test.form")
                .parentDeploymentId(deployment.getId())
                .deploy();
        FormDefinition formDefinition = formRepositoryService.createFormDefinitionQuery().deploymentId(formDeployment.getId()).singleResult();
        String formDefinitionId = formDefinition.getId();



        //啟動(dòng)實(shí)例并且設(shè)置表單的值
        String outcome = "shareniu";
        Map<String, Object> formProperties;
        formProperties = new HashMap<>();
        formProperties.put("reason", "家里有事");
        formProperties.put("startTime", Dates.format(new Date(), Dates.Pattern.DATE));
        formProperties.put("endTime", Dates.format(new Date(), Dates.Pattern.DATE));
        String processInstanceName = "shareniu";
        runtimeService.startProcessInstanceWithForm(processDefinitionId, outcome, formProperties, processInstanceName);
        HistoricProcessInstanceEntity historicProcessInstanceEntity = (HistoricProcessInstanceEntity )historyService.createHistoricProcessInstanceQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        String processInstanceId = historicProcessInstanceEntity.getProcessInstanceId();



        //查詢表單信息
        FormModel fm = runtimeService.getStartFormModel(processDefinitionId, processInstanceId);
        System.out.println(fm.getId());
        System.out.println(fm.getKey());
        System.out.println(fm.getName());
        System.out.println(fm.getOutcomeVariableName());
        System.err.println(fm.getVersion());
        List<FormField> fields = fm.getFields();
        for (FormField ff : fields) {
            System.out.println("######################");
            System.out.println(ff.getId());
            System.out.println(ff.getName());
            System.out.println(ff.getType());
            System.out.println(ff.getPlaceholder());
            System.out.println(ff.getValue());
            System.out.println("######################");

        }


        //查詢個(gè)人任務(wù)并填寫表單
        Map<String, Object> formProperties2 = new HashMap<>();
        formProperties2.put("reason", "家里有事2222");
        formProperties2.put("startTime", Dates.format(new Date(), Dates.Pattern.DATE));
        formProperties2.put("endTime", Dates.format(new Date(), Dates.Pattern.DATE));
        formProperties2.put("days", "3");
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        String taskId = task.getId();
        String outcome2="牛哥";
        taskService.completeTaskWithForm(taskId, formDefinitionId, outcome2, formProperties2);

        //獲取個(gè)人任務(wù)表單
        FormModel taskFM = taskService.getTaskFormModel(taskId);
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末稍刀,一起剝皮案震驚了整個(gè)濱河市撩独,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖综膀,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澳迫,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡剧劝,警方通過查閱死者的電腦和手機(jī)纲刀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來担平,“玉大人示绊,你說我怎么就攤上這事≡萋郏” “怎么了面褐?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長取胎。 經(jīng)常有香客問我展哭,道長,這世上最難降的妖魔是什么闻蛀? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任匪傍,我火速辦了婚禮,結(jié)果婚禮上觉痛,老公的妹妹穿的比我還像新娘役衡。我一直安慰自己,他們只是感情好薪棒,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布手蝎。 她就那樣靜靜地躺著,像睡著了一般俐芯。 火紅的嫁衣襯著肌膚如雪棵介。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天吧史,我揣著相機(jī)與錄音邮辽,去河邊找鬼。 笑死贸营,一個(gè)胖子當(dāng)著我的面吹牛吨述,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播莽使,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼锐极,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼笙僚!你這毒婦竟也來了芳肌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亿笤,沒想到半個(gè)月后翎迁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡净薛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年汪榔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肃拜。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痴腌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出燃领,到底是詐尸還是另有隱情士聪,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布猛蔽,位于F島的核電站剥悟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏曼库。R本人自食惡果不足惜区岗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毁枯。 院中可真熱鬧慈缔,春花似錦、人聲如沸种玛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒂誉。三九已至教藻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間右锨,已是汗流浹背括堤。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绍移,地道東北人悄窃。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像蹂窖,于是被迫代替她去往敵國和親轧抗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344