bind语法
版本支持:v2.13.0+
# 绑定静态数据
LiteFlow还提供了bind
语法关键字,它和data
使用场景是一致的,但是它和data
关键不同的是,它允许绑定KV键值对,比如
<chain id="chain1">
THEN(a.bind("k1", "test"), b);
</chain>
你可以在组件中通过getBindData
方法来获取:
@LiteflowComponent("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String bindValue = this.getBindData("k1", String.class);
...
}
}
当然bind的时候也可以把value设置成json字符串,那么在取值的时候,第二个参数就可以传相应的VO的class,LiteFlow内部可以自动把Json转型成对象。
bind
关键字也可以用作于表达式,子变量,chain上,其意义是被赋值的表达式/子变量/chain里所有的组件都绑定了相同的值,比如:
<chain id="chain1">
THEN(a,b).bind("k1","test");
</chain>
<chain id="chain2">
THEN(SWITCH(y).TO(d,c), WHEN(a, b), IF(x, c, d)).bind("k1", "test")
</chain>
<chain id="sub">
THEN(a,IF(NOT(x), b, c));
</chain>
<chain id="chain3">
THEN(d, sub.bind("k1", "test2"))
</chain>
# 绑定动态数据
LiteFlow还允许用bind
关键字去绑定动态数据,这是tag
和data
关键字无法做到的。
所谓动态数据就是在编写规则EL的时候无法确定的,你可以bind一个表达式,LiteFlow会根据你bind的表达式去上下文中去搜索所需要的数据。
bind动态数据,value必须为一个表达式,且格式为${表达式}
。
比如你的上下文如下:
public class OrderContext {
private Integer id;
private String orderCode;
private Member member;
//getter setter 省略
}
// Member对象定义如下:
public class Member {
private String memberCode;
private String memberName;
//getter setter 省略
}
规则如下:
<chain id="chain1">
THEN(a, b.bind("k1", "${orderCode}"))
</chain>
那么在b组件中就可以通过this.getBindData("k1", String.class)
拿到上下文中orderCode的值。
如果想拿到上面OrderContext
中Member
对象中的memberName
对象,你可以通过点操作符得到:
<chain id="chain1">
THEN(a, b.bind("k1", "${member.memberName}"))
</chain>
如果你除了OrderContext
还传了其他上下文,以上表达式也是可以得到的具体值的。因为LiteFlow会智能的根据你上下文中去匹配你的表达式。
但是如果有种极端情况,就是假设你传了OrderContext
,又传了UserContext
,两个上下文都有id
属性,那么如果你写以下表达式:
<chain id="chain1">
THEN(a, b.bind("k1", "${id}"))
</chain>
那么bind的到底是哪个上下文里的id呢?
这里如果你不指定,永远是bind第一个上下文的id,那么如果你要指定绑定UserContet
里的id
怎么办呢?
这时候就需要指定上下文了,你可以这样指定:
<chain id="chain1">
THEN(a, b.bind("k1", "${userContext.id}"))
</chain>
这个userContext
是UserContext
的首字符小写的形式。你也可以通过@ContextBean
去改变,比如你这样定义:
@ContextBean("userCx")
public class UserContext {
private Integer id;
private String address;
//getter setter 省略
那么你就可以这样去指定了:
<chain id="chain1">
THEN(a, b.bind("k1", "${userCx.id}"))
</chain>
注意点1
其实在多上下文中属性名不冲突的情况,官方建议不要指定上下文,直接智能匹配。
注意点2
绑定动态数据除了绑定在节点上,同样可以绑定在表达式,子变量,chain上。
# bind语法的覆盖用法v2.13.1+
bind语法如果同时在节点和表达式上同时使用,是不会相互覆盖的,比如:
<chain id="chain1">
THEN(a, b.bind("k","v1"), c).bind("k", "v2");
</chain>
上述表达式a拿到的是v2,b拿到的是v1,c拿到的是v2,b并不会被表达式上的bind给覆盖。
那如果想把b也强制覆盖成v2,则可以这么使用:
<chain id="chain1">
THEN(a, b.bind("k","v1"), c).bind("k", "v2", true);
</chain>
bind最后一个参数传true的话,那么bind里的所有节点,都会被强制覆盖。以上表达式a,b,c拿到的都是v2了。