导图社区 LiteFlowEL规则属性分析
这是一篇关于LiteFlowEL规则属性分析的思维导图,LiteFlow是一种流程管理工具,其EL规则依托于底层的表达式语言进行扩展和封装。它提供了一种灵活且可扩展的方式来定义和执行任务。
编辑于2024-01-11 17:48:59LiteFlowEL规则属性分析
说明
核心作用
规则编排
流程的表达式
规则
串行编排
THEN
并行编排
WHEN
子关键词ignoreError
默认为false
忽略错误的特性
子关键词any
默认为false
任一节点先执行完则忽略其他
开启WHEN线程池隔离
目前liteflow设计里when线程池,如果你不单独设置自定义线程池,那么就会用默认的线程池。
而这个线程池,是所有的when共同一个。
LiteFlow从2.11.1开始,提供一个liteflow.when-thread-pool-isolate参数,默认为false,如果设为true,则会开启WHEN的线程池隔离机制,这意味着每一个when都会有单独的线程池。这个特性对于运行复杂的嵌套when时是可以提升运行速度的且规避掉一些锁的问题。
配置
liteflow.when-thread-pool-isolate=true
关于组的概念
用EL表达式,其实你写2个不同的WHEN就是2个组
<chain name="chain1"> THEN( WHEN(a, b, c, d) ); </chain>
<chain name="chain1"> THEN( WHEN(a, b), WHEN(c, d) ); </chain>
选择编排
SWITCH...TO
DEFAULT关键字
SWITCH...TO...DEFAULT
<chain name="chain1"> SWITCH(x).TO(a, b, c).DEFAULT(y); </chain>
如上表达式的x如果返回非a,b,c中的一个,则默认选择到y。当然DEFAULT里面也可以是一个表达式。
选择编排中的id语法
LiteFlow中规定,每个表达式都可以有一个id值,你可以设置id值来设置一个表达式的id值。然后在选择组件里返回这个id即可。
示例
<chain name="chain1"> THEN( a, SWITCH(b).to( c, THEN(d, e).id("t1") ), f ); </chain>
@LiteflowComponent("b") public class BCmp extends NodeSwitchComponent { @Override public String processSwitch() throws Exception { //do your biz return "t1"; } }
选择编排中的tag语法
给表达式赋值tag属性,通过这个tag在选择节点中返回
示例
<chain name="chain1"> THEN( a, SWITCH(b).to( c, THEN(d, e).tag("t1") ), f ); </chain>
@LiteflowComponent("b") public class BCmp extends NodeSwitchComponent { @Override public String processSwitch() throws Exception { return "tag:t1"; //以下这种也是可以的 return ":t1"; } }
条件编排
条件编排是选择编排一个变种,选择编排是根据逻辑去选择多个子项中的一项。而条件编排只有真和假2个子项,这处理某些业务的过程中非常有用。
IF的二元表达式
<chain name="chain1"> THEN( IF(x, a), b ); </chain>
IF的三元表达式
<chain name="chain1"> THEN( IF(x, a, b), c ); </chain>
ELSE表达式
LiteFlow也提供了ELSE表达式,IF的二元表达式+ELSE表达式等同于IF三元表达式,比如:
<chain name="chain1"> IF(x, a).ELSE(b); </chain>
等同于
<chain name="chain1"> IF(x, a, b); </chain>
ELIF表达式
ELIF关键字的用法其实和java语言的else if类似,可以跟多个,和IF二元表达式参数一样,一般最后还会跟个ELSE,用于多重条件的判断:
<chain name="chain1"> IF(x1, a).ELIF(x2, b).ELIF(x3, c).ELIF(x4, d).ELSE(THEN(m, n)); </chain>
注意一
值得注意的是,只有IF的二元表达式后面才能跟ELIF,如果IF三元表达式后面跟ELIF,最后一个表达式会被ELIF的表达式覆盖,就比如:
<chain name="chain1"> IF(x1, a, b).ELIF(x2, c).ELSE(d); </chain>
这样x1即使为false,也不会执行到b,会去判断x2。虽然框架做了容错处理,但是我们在写表达式的时候,不推荐这样写。容易造成理解上的困扰。
注意二
其实IF三元表达式已经能表达一切的可能了,有多重条件也可以不用ELIF,可以用嵌套来完成,比如:
<chain name="chain1"> IF( x1, a, IF( x2, b, IF(x3, c, d) ) ); </chain>
但是官方依旧不推荐你这么写,多重嵌套在理解起来会比较吃力,所以尽量用ELIF来代替。
循环编排
FOR循环
WHILE循环
ITERATOR迭代循环
BREAK
LiteFlow同样也支持BREAK语法,代表退出循环。
BREAK关键字可以跟在FOR和WHILE后面,通常用法为:
<chain name="chain1"> FOR(f).DO(THEN(a, b)).BREAK(c); </chain>
<chain name="chain1"> WHILE(w).DO(THEN(a, b)).BREAK(c); </chain>
其中c这个节点需要为退出循环组件,返回一个布尔值,为true则退出循环。如何定义请参考退出循环组件。
BREAK关键字是在每次循环的末尾进行判断的。
异步循环
次数循环表达式、条件循环表达式以及迭代循环表达式等循环表达式,可以使用parallel子关键字(默认为false)来配置循环子项的执行方式,使其成为异步模式的循环表达式(所谓异步模式,就是各个循环子项之间并行执行)。
<chain name="chain1"> FOR(2).parallel(true).DO(THEN(a,b,c)); </chain>
<chain name="chain6"> WHILE(x).parallel(true).DO(THEN(a,b,c)); </chain>
<chain name="chain7"> ITERATOR(x).parallel(true).DO(THEN(a,b,c)); </chain>
注意
parallel子关键字只能用于次数循环表达式、条件循环表达式以及迭代循环表达式等循环表达式。
对于异步模式的条件循环表达式,会不断创建并行执行循环子项,直到条件不满足为止。
异步模式依然支持BREAK,当退出循环组件返回为true时,会停止向线程池提交新的任务,但是已经提交的任务会继续执行。循环组件会在所有已提交任务执行完毕后退出。
默认情况下,异步模式的下各循环子项会在liteFlow提供的默认异步循环线程池中执行,并且可以通过如下两个参数来控制默认线程池的workers数目和队列长度
<!--配置默认线程池的worker数目--> liteflow.parallelLoop-max-workers=16 <!--配置默认线程池的队列长度--> liteflow.parallelLoop-queue-limit=512
当然,也可以通过自定义线程池来执行异步模式的循环子项,只需要在配置文件中进行如下配置即可,不过此时上述两个参数将不再生效。
<!--用户可以直接指定自定义的线程池全类名的方式指定异步循环线程池--> liteflow.parallelLoop-executor-class=com.yomahub.liteflow.test.customThreadPool.CustomThreadBuilder
捕获异常表达式
CATCH...DO
例1
<chain name="chain1"> CATCH( THEN(a,b) ).DO(c) </chain>
上述语法表示,如果a组件出现异常并抛出,则不会执行b组件,会直接执行c组件。
在c组件中,可以通过this.getSlot().getException()来获取异常。
同时,当用了CATCH表达式之后,即便在CATCH包裹的组件有异常抛出,整个流程返回的LiteflowResponse中的isSuccess方法仍然为true,getCause中也没有任何的Exception。如果你写过java程序,应该会对这样的机制很容易理解。因为异常已经被你自己处理掉了。
例2
同时CATCH也可以不加DO,比如:
<chain name="chain1"> THEN( CATCH( THEN(a,b) ), c ) </chain>
上面这段表达式不管a,b有没有抛出异常,最终总会执行c。如果a抛出异常,那么最终执行链路就为a==>c
搭配循环使用
CATCH表达式和循环表达式搭配起来使用,还能做出java中continue的效果,比如:
<chain name="chain1"> FOR(x).DO( CATCH( THEN(a,b,c) ) ) </chain>
如果你希望在b组件中达成某一个条件就不执行c,继续循环,那么你可以借助CATCH语法,只要在b组件中往外抛一个异常即可。
或与非表达式
表达词
AND
OR
NOT
编排需要返回一个布尔值
<chain name="chain1"> IF(x, a, b); </chain>
其中x组件应该为条件组件,返回的是一个布尔值。
但是如果这个布尔值并不是由一个组件决定的,而是由多个组件决定的呢。这里就可以用与或非表达式了。
假设这里的条件是要由x和y共同决定,利用与或非表达式中的AND:
<chain name="chain1"> IF(AND(x,y), a, b); </chain>
上述AND的意思是,如果x和y都为true,则为真,会执行组件a,如果x和y有一个为false,则执行b。
AND里面可以有多个布尔组件或者与或非表达式。
同理,这里也可以用OR来表示:
<chain name="chain1"> IF(OR(x,y), a, b); </chain>
上述OR的意思是,只要x和y中的一个为true,则为真,否则为假。
OR里面可以有多个组件或者与或非表达式。
NOT就是非的意思,比如:
<chain name="chain1"> IF(NOT(x), a, b); </chain>
如果x返回true,则经过非运算后,为假,执行b,如果x返回false,则经过非运算后,为真,执行a。
NOT里面只能有一个布尔组件或者与或非表达式。
可以用的地方
在LiteFlow所有EL表达式中,返回布尔值的地方都可以用与或非表达式,除了上述的IF外,还可以用在WHILE,BREAK表达式中。
如果你在THEN表达式中用与或非表达式,会报错的,因为普通组件并非是一个布尔值的的返回。
使用子流程
<chain name="chain4"> THEN( A, B, WHEN( THEN(C, WHEN(J, K)), D, THEN(H, I) ), SWITCH(X).to( M, N, WHEN(Q, THEN(P, R)).id("w01") ), Z ); </chain>
使用子流程优化
<chain name="mainChain"> THEN( A, B, WHEN(chain1, D, chain2), SWITCH(X).to(M, N, chain3), z ); </chain>
<chain name="chain1"> THEN(C, WHEN(J, K)); </chain>
<chain name="chain2"> THEN(H, I); </chain>
<chain name="chain3"> WHEN(Q, THEN(P, R)).id("w01"); </chain>
使用子变量
子变量流程
<chain> t1 = THEN(C, WHEN(J, K)); w1 = WHEN(Q, THEN(P, R)).id("w01"); t2 = THEN(H, I); THEN( A, B, WHEN(t1, D, t2), SWITCH(X).to(M, N, w1), Z ); </chain>
复杂编排例子
主题