日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Flowable流程部署與刪除

本文我們一起來(lái)看看流程的部署等細(xì)節(jié)問(wèn)題。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)灌南免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了成百上千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

其實(shí)當(dāng)我們使用了 Spring Boot 之后,默認(rèn)情況下流程是會(huì)自動(dòng)部署的,基本上不需要我們額外做什么事情。不過(guò)這些操作里還是有不少細(xì)節(jié),今天松哥就來(lái)帶大家一起來(lái)梳理一下。

1. 默認(rèn)行為

首先我們先來(lái)梳理一下默認(rèn)行為。

默認(rèn)情況下,我們放在 resources/processes 目錄下的所有流程文件會(huì)自動(dòng)被部署,流程文件的后綴有兩種形式 bpmn20.xml 或者 bpmn。當(dāng)然,無(wú)論是存放流程文件的位置,還是流程文件的格式,都是可以定制的,涉及到的屬性主要有三個(gè),可在 application.properties 中進(jìn)行配置:

flowable.check-process-definitions=false
flowable.process-definition-location-prefix=classpath*:/processes/
flowable.process-definition-location-suffixes=**.bpmn20.xml,**.bpmn

flowable.check-process-definitions:這個(gè)表示是否在項(xiàng)目啟動(dòng)的時(shí)候,去檢查文件目錄是否有對(duì)應(yīng)的流程文件,該屬性為 true 表示如果有流程文件就自動(dòng)部署,false 表示不檢查,那么也就不會(huì)自動(dòng)部署。

flowable.process-definition-location-prefix?:這個(gè)是流程文件的位置,默認(rèn)就是 classpath*:/processes/,當(dāng)然開(kāi)發(fā)者也可以進(jìn)行配置。

flowable.process-definition-location-suffixes?:這個(gè)是流程文件的后綴,默認(rèn)有兩個(gè),分別是 **.bpmn20.xml 和 **.bpmn,當(dāng)然開(kāi)發(fā)者也可以進(jìn)行配置。

這個(gè)配置應(yīng)該沒(méi)啥好說(shuō)的。

2. 動(dòng)態(tài)部署

有的時(shí)候,我們的流程可能并不是提前設(shè)計(jì)好的,而是項(xiàng)目啟動(dòng)之后,動(dòng)態(tài)部署的,例如項(xiàng)目啟動(dòng)成功之后,動(dòng)態(tài)上傳一個(gè)流程的 XML 文件進(jìn)行部署,這也是一種比較常見(jiàn)的場(chǎng)景,對(duì)于這種情況,我們可以按照如下方式進(jìn)行部署:

@RestController
public class ProcessDeployController {

@Autowired
RepositoryService repositoryService;

@PostMapping("/deploy")
public RespBean deploy(MultipartFile file) throws IOException {
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
.category("javaboy的工作流分類")
.name("javaboy的工作流名稱")
.addInputStream(file.getOriginalFilename(), file.getInputStream())
.key("javaboy的工作流key");
Deployment deployment = deploymentBuilder
.deploy();
return RespBean.ok("部署成功",deployment.getId());
}
}

我這里給了一個(gè)簡(jiǎn)單的文件上傳接口,關(guān)于文件上傳部分我就不多說(shuō)了。我們來(lái)看下流程部署:

首先通過(guò) repositoryService.createDeployment() 方法來(lái)創(chuàng)建一個(gè)流程部署構(gòu)建器,即 DeploymentBuilder。

接下來(lái)為 DeploymentBuilder 設(shè)置分類、名稱以及 key 等屬性。

關(guān)鍵的方法是 addInputStream,通過(guò)該方法去指定流程文件。官方的提供的指定流程文件的方式有好幾種;除了 addInputStream 之外,另外還有一個(gè) addString,這個(gè)就是將流程文件轉(zhuǎn)為一個(gè)字符串傳入進(jìn)來(lái);addBytes 是將流程文件轉(zhuǎn)為字節(jié)數(shù)組傳進(jìn)來(lái);addClasspathResource 方法則是直接從 classpath 目錄下去加載流程文件,這幾個(gè)方法根據(jù)自己的使用場(chǎng)景選擇一個(gè)合適的方法去調(diào)用即可。

這里有一個(gè)需要跟大家強(qiáng)調(diào)的地方,就是 addInputStream/addBytes/addString 等方法都需要設(shè)置資源名,這個(gè)名稱是可以隨意設(shè)置的,但是注意名稱的后綴,需要是 bpmn20.xml 或者 bpmn,否則流程沒(méi)有部署。為什么流程名后綴要是 bpmn20.xml 或者 bpmn 呢?參考第一小節(jié)。

3. 表分析

在我們的流程部署過(guò)程中,一共有三張表參與到我們的工作中了,雖然松哥之前已經(jīng)寫(xiě)過(guò)文章和大家梳理 flowable 中各個(gè)數(shù)據(jù)表的作用,不過(guò)當(dāng)時(shí)只是大致上介紹了一下,沒(méi)有細(xì)說(shuō),這次我們就先來(lái)看看這次涉及到的三張表。

ACT_RE_DEPLOYMENT

這個(gè)表是流程部署表,每部署一個(gè)流程,這張表中就會(huì)新增一條記錄,用來(lái)描述我們剛剛定義好的流程:

這里的 ID_、NAME_、CATEGORY_ 等等,就是我們?cè)诓渴鹆鞒痰臅r(shí)候設(shè)置的參數(shù)。

ACT_RE_PROCDEF

這是流程定義表,我們每定義的一個(gè)流程,都會(huì)記錄在這張表中:

這張表中的字段比較多,我這里只是列出來(lái)了其中一部分。這這表中有一個(gè) DEPLOYMENT_ID 字段,和 ACT_RE_DEPLOYMENT 表進(jìn)行關(guān)聯(lián),所以 ACT_RE_DEPLOYMENT 和 ACT_RE_PROCDEF 表的關(guān)系,其實(shí)是一對(duì)一的關(guān)系,部署表中的一條記錄對(duì)應(yīng)定義表中的一條記錄。

另外,該表中有一個(gè) CATEGORY_ 的字段,這個(gè)字段表示流程的分類,注意這個(gè)和部署的分類可不一樣,流程部署的分類參數(shù)第二小節(jié)的代碼,流程的分類,說(shuō)白了其實(shí)就是我們流程定義 XML 文件中的 targetNamespace 屬性,如下圖:

大家可根據(jù)自己的實(shí)際需求去修改 targetNamespace 屬性的值,這個(gè)值改了之后,ACT_RE_PROCDEF 表中的 CATEGORY_ 字段也會(huì)跟著發(fā)生變化。

另外,該表中還有一個(gè) VERSION_ 字段,這個(gè)看名字就知道是描述記錄的版本號(hào),當(dāng)我們修改了流程的內(nèi)容之后,重新部署的時(shí)候,ACT_RE_DEPLOYMENT 表和 ACT_RE_PROCDEF 表均會(huì)自動(dòng)增加一條記錄數(shù),其中,流程定義表 ACT_RE_PROCDEF 中的記錄的 VERSION_ 字段的值會(huì)自動(dòng)加 1,這樣我們就能夠看到不同歷史版本的流程定義。

那么系統(tǒng)是怎么識(shí)別修改后的流程和前一個(gè)流程是同一個(gè)呢?主要是靠流程的 id 屬性,如下圖:

這個(gè)流程的 id 屬性,對(duì)應(yīng)到表中,就是 ACT_RE_PROCDEF 表的 KEY_ 字段。

ACT_GE_BYTEARRAY

涉及到的第三張表是這個(gè)通用數(shù)據(jù)存儲(chǔ)表,這個(gè)表的字段比較少,如下圖:

小伙伴們看到,這個(gè)表中有一個(gè) DEPLOYMENT_ID 字段,這個(gè)就是跟 ACT_RE_DEPLOYMENT 表關(guān)聯(lián)的字段,一條流程部署記錄在 ACT_GE_BYTEARRAY 表中對(duì)應(yīng)兩條記錄,分別是記錄 XML 文件和記錄流程圖片。

這個(gè)表中有一個(gè) BYTES_ 字段,我們部署的流程的 XML 文件就保存在這里,同時(shí),系統(tǒng)默認(rèn)還會(huì)根據(jù) XML 文件生成一張流程圖片,也保存在這里,圖片就像下面這種:

所以一個(gè)流程部署,在這張表中對(duì)應(yīng)兩條記錄,一條記錄 XML 文件,一條記錄流程圖片。

好啦,這就是流程部署涉及到的三張表。

4. 查詢操作

接下來(lái),強(qiáng)烈建議大家在 Spring Boot 的 application.properties 中添加如下配置,開(kāi)啟 flowable 日志:

logging.level.org.flowable=debug

這個(gè)配置表示開(kāi)啟 flowable 的日志,開(kāi)啟日志的好處是我們可以看到底層的 SQL,學(xué)習(xí) flowable,調(diào)用 API 的時(shí)候,不能只掌握 API 的使用,調(diào)用 API 的時(shí)候,心里想著這是操作哪張表,學(xué)起來(lái)更快。

4.1 查詢部署信息

例如我們現(xiàn)在想要查詢流程的部署信息,如下:

@Test
void test01() throws IOException {
List list = repositoryService.createDeploymentQuery().list();
for (Deployment deployment : list) {
logger.info("id:{};key:{}", deployment.getId(), deployment.getKey());
}
}

創(chuàng)建一個(gè)查詢器,然后返回所有的流程部署信息并打印出來(lái),我們看下此時(shí) IDEA 控制臺(tái)打印出來(lái)的 SQL 信息:

可以看到,底層執(zhí)行的 SQL 其實(shí)就是去查詢 ACT_RE_DEPLOYMENT 表。

現(xiàn)在我們?cè)偃タ匆恍┎樵兊姆椒ǎ瑧?yīng)該就很容易明白其含義了:

小伙伴們看到,我們可以利用流程部署的名字、分類、ID 等各種信息去查詢,可以精確匹配也可以模糊匹配。

例如我想查詢 key 為 javaboy的工作流key 的流程部署文件,但是這個(gè)流程我之前部署過(guò)多次(版本升級(jí)),現(xiàn)在我想查詢最近一次的流程部署信息,查詢方式如下:

@Test
void test01() throws IOException {
Deployment deployment = repositoryService.createDeploymentQuery().deploymentKey("javaboy的工作流key").latest().singleResult();
logger.info("id:{};key:{}", deployment.getId(), deployment.getKey());
}

我們來(lái)看下控制臺(tái)打印出來(lái)的 SQL:

--- [           main] i.p.e.D.selectDeploymentsByQueryCriteria : ==>  Preparing: SELECT RES.* from ACT_RE_DEPLOYMENT RES WHERE RES.KEY_ = ? and RES.DEPLOY_TIME_ = (select max(DEPLOY_TIME_) from ACT_RE_DEPLOYMENT where KEY_ = RES.KEY_ and DERIVED_FROM_ is null and ( (TENANT_ID_ IS NOT NULL and TENANT_ID_ = RES.TENANT_ID_) or (TENANT_ID_ IS NULL and RES.TENANT_ID_ IS NULL) ) ) order by RES.ID_ asc
--- [ main] i.p.e.D.selectDeploymentsByQueryCriteria : ==> Parameters: javaboy的工作流key(String)
--- [ main] i.p.e.D.selectDeploymentsByQueryCriteria : <== Total: 1

這個(gè) SQL 寫(xiě)的有點(diǎn)復(fù)雜,但是仔細(xì)看就一個(gè)意思,給定查詢的 key 是 javaboy的工作流key,查詢時(shí)間是一個(gè)最大的時(shí)間,這就很好懂了。

4.2 查詢流程定義信息

接下來(lái)我們?cè)賮?lái)看看查詢流程的定義信息。查詢所有的流程定義信息,如下:

@Test
void test02() {
List list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition pd : list) {
logger.info("id:{};key:{};version:{};",pd.getId(),pd.getKey(),pd.getVersion());
}
}

來(lái)看看控制臺(tái)打印的 SQL:

可以看到,就是去流程定義表 ACT_RE_PROCDEF 去查看所有。

基于此,其他的查詢 API 就都好理解了,例如根據(jù)流程定義的 KEY 去查詢所有的流程定義,這個(gè) KEY 其實(shí)就是流程定義 XML 文件中的 id:

@Test
void test02() {
List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("javaboy_submit_an_expense_account").list();
for (ProcessDefinition pd : list) {
logger.info("id:{};key:{};version:{};",pd.getId(),pd.getKey(),pd.getVersion());
}
}

我們來(lái)看下查詢 SQL:

其他的查詢 API 我就不挨個(gè)演示了,方法基本上都是見(jiàn)名知意的。

4.3 原生查詢

要是覺(jué)得用 API 查詢 不過(guò)癮,我們也可以自己寫(xiě) SQL 查詢。

跟前面一樣,例如我想查詢 key 為 javaboy的工作流key 的流程部署文件,但是這個(gè)流程我之前部署過(guò)多次(版本升級(jí)),現(xiàn)在我想查詢最近一次的流程部署信息,查詢方式如下:

@Test
void test03() {
Deployment deployment = repositoryService.createNativeDeploymentQuery().sql("SELECT RES.* from ACT_RE_DEPLOYMENT RES WHERE RES.KEY_ = #{key} and RES.DEPLOY_TIME_ = (select max(DEPLOY_TIME_) from ACT_RE_DEPLOYMENT where KEY_ = RES.KEY_) order by RES.ID_ asc").parameter("key", "javaboy的工作流key").singleResult();
logger.info("id:{};key:{}", deployment.getId(), deployment.getKey());
}

自己寫(xiě) SQL 即可,參數(shù)的占位符用 #,因?yàn)檫@里底層的 SQL 操作實(shí)際上是 MyBatis。

相同的道理,我想根據(jù)流程定義的 KEY 去查詢流程定義信息,使用原生查詢方式如下:

@Test
void test04() {
List list = repositoryService.createNativeProcessDefinitionQuery()
.sql("SELECT RES.* from ACT_RE_PROCDEF RES WHERE RES.KEY_ = #{key} order by RES.ID_ asc")
.parameter("key", "javaboy_submit_an_expense_account").list();
for (ProcessDefinition pd : list) {
logger.info("id:{};key:{};version:{};", pd.getId(), pd.getKey(), pd.getVersion());
}
}


網(wǎng)頁(yè)題目:Flowable流程部署與刪除
文章源于:http://m.5511xx.com/article/djjsppd.html