別再用硬編碼寫業(yè)務(wù)流程了工三,試試這款輕量級(jí)流程編排框架

前言

在每個(gè)公司的系統(tǒng)中,總有一些擁有復(fù)雜業(yè)務(wù)邏輯的系統(tǒng)视译,這些系統(tǒng)承載著核心業(yè)務(wù)邏輯蕊唐,幾乎每個(gè)需求都和這些核心業(yè)務(wù)有關(guān),這些核心業(yè)務(wù)業(yè)務(wù)邏輯冗長简十,涉及內(nèi)部邏輯運(yùn)算檬某,緩存操作,持久化操作螟蝙,外部資源調(diào)取恢恼,內(nèi)部其他系統(tǒng)RPC調(diào)用等等。時(shí)間一長胰默,項(xiàng)目幾經(jīng)易手场斑,維護(hù)的成本得就會(huì)越來越高。各種硬代碼判斷牵署,分支條件越來越多漏隐。代碼的抽象,復(fù)用率也越來越低奴迅,各個(gè)模塊之間的耦合度很高青责。一小段邏輯的變動(dòng),會(huì)影響到其他模塊,需要進(jìn)行完整回歸測試來驗(yàn)證脖隶。如要靈活改變業(yè)務(wù)流程的順序扁耐,則要進(jìn)行代碼大改動(dòng)進(jìn)行抽象,重新寫方法浩村。實(shí)時(shí)熱變更業(yè)務(wù)流程做葵?幾乎很難實(shí)現(xiàn)。

開源解決方案

說到流程引擎心墅,開源界有大名鼎鼎的老牌開源軟件JBPM酿矢,也有近幾年非常流行的Activiti和Flowable。他們都是基于BPM協(xié)議怎燥,可以做到基于角色任務(wù)的流傳瘫筐,邏輯的流轉(zhuǎn)。并且很多基于BPM協(xié)議的編輯工具都能做可視化的編輯铐姚。

但今天我要介紹的策肝,是一款輕量級(jí)的流程編排框架——Liteflow。

Liteflow主要致力于邏輯驅(qū)動(dòng)的編排隐绵≈冢可以滿足于大部分的生產(chǎn)業(yè)務(wù)場景。和以上著名的開源流程引擎相比依许,雖然不如他們那么全面棺禾,但是勝在輕量,高性能和極少的學(xué)習(xí)成本峭跳。而且這些項(xiàng)目都是國外開源項(xiàng)目膘婶,集成起來相對比較重,文檔本地化也做的不夠好蛀醉。Liteflow擁有完善的本地文檔和使用范例悬襟。能幫助你的核心系統(tǒng)變得更加靈活,更加易擴(kuò)展拯刁。是一個(gè)解耦你系統(tǒng)的利器脊岳。

https://gitee.com/bryan31/liteFlow

file

Liteflow框架的作用

Liteflow就是為解耦復(fù)雜邏輯而生,如果你要對復(fù)雜業(yè)務(wù)邏輯進(jìn)行新寫或者重構(gòu)垛玻,用liteflow最合適不過割捅。它是一個(gè)輕量,快速的組件式流程引擎框架夭谤,組件編排,幫助解耦業(yè)務(wù)代碼巫糙,讓每一個(gè)業(yè)務(wù)片段都是一個(gè)組件朗儒。

使用Liteflow,你需要去把復(fù)雜的業(yè)務(wù)邏輯按代碼片段拆分成一個(gè)個(gè)小組件,并定義一個(gè)規(guī)則流程配置醉锄。這樣乏悄,所有的組件,就能按照你的規(guī)則配置去進(jìn)行復(fù)雜的流轉(zhuǎn)恳不。同時(shí)Liteflow支持規(guī)則文件的熱加載檩小,即時(shí)完成修改生效。并提供多種持久化規(guī)則的方式的擴(kuò)展烟勋。

Liteflow的設(shè)計(jì)原則

Liteflow是基于工作臺(tái)模式進(jìn)行設(shè)計(jì)的规求,何謂工作臺(tái)模式?

n個(gè)工人按照一定順序圍著一張工作臺(tái)卵惦,按順序各自生產(chǎn)零件阻肿,生產(chǎn)的零件最終能組裝成一個(gè)機(jī)器,每個(gè)工人只需要完成自己手中零件的生產(chǎn)沮尿,而無需知道其他工人生產(chǎn)的內(nèi)容丛塌。每一個(gè)工人生產(chǎn)所需要的資源都從工作臺(tái)上拿取,如果工作臺(tái)上有生產(chǎn)所必須的資源畜疾,則就進(jìn)行生產(chǎn)赴邻,若是沒有,就等到有這個(gè)資源啡捶。每個(gè)工人所做好的零件姥敛,也都放在工作臺(tái)上。

這個(gè)模式有幾個(gè)好處:

  • 每個(gè)工人無需和其他工人進(jìn)行溝通届慈。工人只需要關(guān)心自己的工作內(nèi)容和工作臺(tái)上的資源徒溪。這樣就做到了每個(gè)工人之間的解耦和無差異性。
  • 即便是工人之間調(diào)換位置金顿,工人的工作內(nèi)容和關(guān)心的資源沒有任何變化臊泌。這樣就保證了每個(gè)工人的穩(wěn)定性。
  • 如果是指派某個(gè)工人去其他的工作臺(tái)揍拆,工人的工作內(nèi)容和需要的資源依舊沒有任何變化渠概,這樣就做到了工人的可復(fù)用性。
  • 因?yàn)槊總€(gè)工人不需要和其他工人溝通嫂拴,所以可以在生產(chǎn)任務(wù)進(jìn)行時(shí)進(jìn)行實(shí)時(shí)工位更改:替換播揪,插入,撤掉一些工人筒狠,這樣生產(chǎn)任務(wù)也能實(shí)時(shí)的被更改猪狈。這樣就保證了整個(gè)生產(chǎn)任務(wù)的靈活性。

這個(gè)模式映射到Liteflow框架里辩恼,工人就是組件雇庙,工人坐的順序就是流程配置谓形,工作臺(tái)就是上下文,資源就是參數(shù)疆前,最終組裝的這個(gè)機(jī)器就是這個(gè)業(yè)務(wù)寒跳。正因?yàn)橛羞@些特性,所以Liteflow能做到統(tǒng)一解耦的組件和靈活的裝配竹椒。

springboot里快速配置

Liteflow支持了springboot的自動(dòng)裝配童太,當(dāng)然Liteflow也為非springboot和非spring的項(xiàng)目也提供了支持,這里僅以springboot項(xiàng)目為示例進(jìn)行介紹:

依賴最新的依賴包:

<dependency>
  <groupId>com.yomahub</groupId>
  <artifactId>liteflow-spring-boot-starter</artifactId>
  <version>2.3.3</version>
</dependency>

配置上規(guī)則路徑:

liteflow.rule-source=config/flow.xml

定義組件

Liteflow希望用戶把復(fù)雜邏輯拆分成一個(gè)個(gè)可復(fù)用的組件胸完,所以你得定義你的組件书释,組件的定義很簡單,你需要繼承NodeComponent類舶吗,然后實(shí)現(xiàn)process 方法就行征冷,以下為示例:

@Component("test")
public class TestComponent extends NodeComponent {

 @Override
 public void process() {
  Slot slot = this.getSlot();//slot為這個(gè)請求的上下文
  //這里為你的業(yè)務(wù)處理邏輯
 }
}

這里會(huì)有童鞋問,我的業(yè)務(wù)方法需要入?yún)⒑统鰠⒃趺崔k誓琼,如何傳遞呢检激?

Liteflow為每個(gè)線程都自動(dòng)分配了唯一的一個(gè)slot,可以理解為上下文腹侣。想一想上面說的那個(gè)模型叔收,每個(gè)組件不需要和其他組件進(jìn)行信息互通,所需要的參數(shù)從slot里取就是了傲隶,同時(shí)饺律,執(zhí)行完業(yè)務(wù)邏輯之后,把結(jié)果也放入slot里跺株。所以每個(gè)組件都是獨(dú)立的無參構(gòu)造复濒,這樣就消除了每個(gè)組件的差異性。

這里的slot能貫穿所有組件乒省,每一個(gè)組件都可以訪問到slot里所有的數(shù)據(jù)巧颈。當(dāng)然每個(gè)請求之間的slot,Liteflow做了嚴(yán)格的隔離袖扛,不用擔(dān)心數(shù)據(jù)會(huì)串的問題砸泛。

Liteflow提供的默認(rèn)Slot是一個(gè)弱類型的對象,這里建議使用者自己定義一個(gè)值對象蛆封,只需要繼承AbsSlot類唇礁,便可成為你自己的Slot。更加貼合業(yè)務(wù)惨篱。

組件除了必須要實(shí)現(xiàn)的process 方法盏筐,還有幾個(gè)可選實(shí)現(xiàn):

isAccess:表示是否進(jìn)入該節(jié)點(diǎn),可以用于業(yè)務(wù)參數(shù)的預(yù)先判斷

isContinueOnError:表示出錯(cuò)是否繼續(xù)往下執(zhí)行下一個(gè)組件砸讳,默認(rèn)為false

isEnd:表示是否立即結(jié)束整個(gè)流程 琢融,默認(rèn)為false楷拳,也可以在業(yè)務(wù)日志里根據(jù)業(yè)務(wù)判斷來調(diào)用this.setIsEnd(true)來結(jié)束整個(gè)流程。

@Component("test")
public class TestComponent extends NodeComponent {

 @Override
 public void process() {
  Slot slot = this.getSlot();//slot為這個(gè)請求的上下文
  //這里為你的業(yè)務(wù)處理邏輯
 }
  
  @Override
 public boolean isAccess() {
  Slot slot = this.getSlot();
  //這里做你的參數(shù)檢查吏奸,如果沒獲取到必須的業(yè)務(wù)參數(shù),就不會(huì)進(jìn)入該組件
  boolean checkResult = true;//模擬檢查結(jié)果為true
  return checkResult;
 }
  
  @Override
 public boolean isContinueOnError() {
  return super.isContinueOnError();//默認(rèn)為false
 }
  
  @Override
 public boolean isEnd() {
  return super.isEnd();//默認(rèn)為false
 }
}

你只需定義你的業(yè)務(wù)組件陶耍,之后奋蔚,在啟動(dòng)時(shí),Liteflow會(huì)自動(dòng)掃描到你定義的所有組件烈钞,并進(jìn)行加載泊碑。

編輯規(guī)則文件

實(shí)現(xiàn)完了組件之后,你需要定義規(guī)則文件毯欣,之前規(guī)則文件的路徑配置在了config/flow.xml中馒过,所以我們要編輯這個(gè)文件。

Liteflow的規(guī)則文件定義非常簡單好理解酗钞。簡單的配置腹忽,但是能覆蓋大部分的應(yīng)用場景。

先來看一個(gè)示例:

<chain name="chain1">
    <then value="a,c"/> 
    <when value="b,d"/> 
    <then value="e,f,g"/>
</chain>

在Liteflow中砚作,定義了then和when兩種線程執(zhí)行方式窘奏,then代表串行,上面的示例中葫录,c必須要等a執(zhí)行完才能執(zhí)行着裹。when代表并行,上面的示例中米同,b,d同時(shí)執(zhí)行骇扇。并且b,d都執(zhí)行完了,下面的e面粮,f少孝,g才能挨個(gè)順序執(zhí)行。

再來看個(gè)稍微復(fù)雜點(diǎn)的:

<chain name="chain1">
   <then value="a,c(b|d)"/> 
   <then value="e,f,g"/>
</chain>

Liteflow提供了條件組件但金,這種節(jié)點(diǎn)的職責(zé)就是路由韭山,根據(jù)業(yè)務(wù)邏輯來路由到b節(jié)點(diǎn)還是d節(jié)點(diǎn)。

條件組件的定義示例如下冷溃,需要去繼承NodeCondComponent這個(gè)類钱磅,最終返回的b就是最終要路由到的節(jié)點(diǎn)

@Component("c")
public class CComponent extends NodeCondComponent {

 @Override
 public String processCond() throws Exception {
    //你的業(yè)務(wù)邏輯
  return "b";
 }
}

Liteflow允許你編輯嵌套的流程,例子如下:

<chain name="chain1">
  <then value="a,c,strategy1,g"/>
</chain>

<chain name="strategy1">
  <then value="m(m1|m2|strategy2)"/>
</chain>

<chain name="strategy2">
  <then value="q,p(p1|p2)"/>
</chain>

在這個(gè)例子中似枕,這3條鏈路是串起來執(zhí)行的盖淡,在xml里,可以寫你的組件id凿歼,也可以寫流程id褪迟。配合之前的例子冗恨,是不是能表達(dá)的流程就更加豐富了點(diǎn)呢。

以上3個(gè)例子涵蓋了Liteflow最主要的功能味赃,當(dāng)然Liteflow還提供一些其他的特性掀抹,比如如何進(jìn)行循環(huán)執(zhí)行,如何打印步驟心俗,并且Liteflow還提供了一個(gè)簡易的監(jiān)控模塊傲武,用于統(tǒng)計(jì)你的組件執(zhí)行情況。這里就不一一介紹了城榛。具體你可以點(diǎn)擊Liteflow的Gitee主頁進(jìn)行查看:

https://gitee.com/bryan31/liteFlow

示例工程

為了方便用戶的使用揪利,Liteflow在項(xiàng)目里提供了一個(gè)測試用例,你可以直接拿來跑:

file

同時(shí)作者還做了一個(gè)帶簡單業(yè)務(wù)的示例工程狠持,來演示如何具體實(shí)踐:

https://gitee.com/bryan31/liteflow-example

這個(gè)簡單業(yè)務(wù)是一個(gè)電商場景的價(jià)格計(jì)算的案例疟位,如何通過拆分組件來組合不同的影響價(jià)格的業(yè)務(wù)。并且這個(gè)示例工程還提供了一個(gè)簡單的頁面供大家進(jìn)行調(diào)試:

file

最后

在流程編排開源上喘垂,國內(nèi)一直沒有特別著名的開源項(xiàng)目甜刻。Liteflow的體量雖然無法和業(yè)界著名的流程引擎相比,但是在某些場景正勒,的確提供了輕量級(jí)的解決方案罢吃。并且Liteflow經(jīng)過了公司生產(chǎn)大流量業(yè)務(wù)的考驗(yàn),在穩(wěn)定性和性能方面有一定保障昭齐。希望Liteflow這個(gè)開源框架能幫助到有這方面業(yè)務(wù)需要的同學(xué)們尿招。

關(guān)于我

我是一個(gè)開源作者,也是一名內(nèi)容創(chuàng)作者阱驾【兔眨「元人部落」是一個(gè)堅(jiān)持做原創(chuàng)的技術(shù)科技分享號(hào),會(huì)一直分享原創(chuàng)的技術(shù)文章里覆,陪你一起成長丧荐。關(guān)注回復(fù)liteflow能加入群聊,這里有很多大佬能和你一起探討技術(shù)喧枷,回答你的問題虹统。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市隧甚,隨后出現(xiàn)的幾起案子车荔,更是在濱河造成了極大的恐慌,老刑警劉巖戚扳,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忧便,死亡現(xiàn)場離奇詭異,居然都是意外死亡帽借,警方通過查閱死者的電腦和手機(jī)珠增,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門超歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蒂教,你說我怎么就攤上這事巍举。” “怎么了凝垛?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵禀综,是天一觀的道長。 經(jīng)常有香客問我苔严,道長,這世上最難降的妖魔是什么孤澎? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任届氢,我火速辦了婚禮,結(jié)果婚禮上覆旭,老公的妹妹穿的比我還像新娘退子。我一直安慰自己,他們只是感情好型将,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布寂祥。 她就那樣靜靜地躺著,像睡著了一般七兜。 火紅的嫁衣襯著肌膚如雪丸凭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天腕铸,我揣著相機(jī)與錄音惜犀,去河邊找鬼。 笑死狠裹,一個(gè)胖子當(dāng)著我的面吹牛虽界,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播涛菠,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼莉御,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了俗冻?” 一聲冷哼從身側(cè)響起礁叔,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迄薄,沒想到半個(gè)月后晴圾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡噪奄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年死姚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了人乓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡都毒,死狀恐怖色罚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情账劲,我是刑警寧澤戳护,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站瀑焦,受9級(jí)特大地震影響腌且,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜榛瓮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一铺董、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧禀晓,春花似錦精续、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凫乖,卻和暖如春确垫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帽芽。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工森爽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嚣镜。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓爬迟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親菊匿。 傳聞我的和親對象是個(gè)殘疾皇子付呕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容