🪴用表达式获取上下文参数
版本支持:v2.13.1+
# 介绍
如果你看过上下文参数注入,一定注意到了,使用上下文参数注入的方式可以让组件和上下文解耦。
但是上下文参数注入
只限于声明式组件使用。有没有通用一点的类似机制呢,使得普通继承式组件也能用?
这就是这个章节带来的表达式取参的功能,这个功能,无论在继承式还是声明式的组件里都可以使用,甚至于在脚本组件里都可以使用。这是真正意义上的通用特性。
# 用表达式获取参数
我们在组件里面写业务,首先肯定就是要拿到上下文,在声明式组件里通常的写法为:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
YourContext context = this.getContextBean(YourContext.class);
String userCode = context.getUserCode();
...
}
}
以上代码,我们从上下文中拿到了上下文,并且从上下文中拿到了userCode
这个参数。
这样写的好处是直观,但是缺点是,如果这是一个公用的组件,那么这个组件就强绑定YourContext
这个对象了。虽然在LiteFlow中,你也可以通过上下文继承的方式或者多上下文的方式来解决。但是都是曲线救国。
现在你可以这样写来获得userCode:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String userCode = this.getContextValue("userCode");
...
}
}
现在这个组件就和你的上下文彻底解耦了,你的上下文中只要有userCode
这个属性的,那都可以被取出来。
如果层级比较深,还可以用点操作符:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String code = this.getContextValue("member.code");
...
}
}
上述表达式,意思是取出上下文中member
这个对象中的code
字段的值。
如果有多个上下文,表达式也会匹配最合适的那个进行取出,你无需关心有多少个上下文,上下文是什么。
但是,你需要注意有一种特例,那就是你在多个上下文中拥有相同的字段,比如现在这个流程中传入了3个上下文:
public class OrderContext{
private String code;
...
}
public class MemberContext{
private String code;
...
}
public class AuthContext{
private String code;
...
}
这时候的this.getContextValue("code");
取出的到底是哪一个呢?
LiteFlow框架在这种情况下 ,只会返回第一个匹配到的字段的值。如果你需要精确指定是某个Context下的code。则需要在表达式中加上上下文的前缀:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String code = this.getContextValue("authContext.code");
...
}
}
这个前缀默认是你的上下文的类名的首字母小写。但是你也可以改变它,它受@ContextBean
这个注解的影响:
@ContextBean("authCxt")
public class AuthContext{
private String code;
...
}
那么你就不能用authContext
这个前缀来取了,而是通过authCtx
来取:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String code = this.getContextValue("authCxt.code");
...
}
}
你除了可以用点操作符,对于常用的List,Map,数组形式也有支持:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
//假设userList是一个List属性,可以按照下标去取
String a = this.getContextValue("userList.get(0)");
//假设dataMap是一个Map属性
String b = this.getContextValue("dataMap.get('key')");
//假设nameArray是一个数组
String c = this.getContextValue("nameArray[0]");
...
}
}
# 用表达式设置参数
除了可以用表达式取出上下文中的参数,在设置参数时,同样可以用表达式:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
String name = this.getContextValue("name");
this.setContextValue("setDesc", "hello," + name);
}
}
以上代码就是从上下文中拿到name
这个值,并且调用上下文中的setDesc
方法,把值设置进去。
同样的,如果有多个上下文的时候,完全不用关心name
是从哪个上下文中来,setDesc
是哪个上下文中的方法。
值得注意的是,this.setContextValue
的定义是:
public void setContextValue(String methodExpress, Object... values){
...
}
所以当你的方法有多个参数的时候,也是可以支持的。
同样的,你也可以用点操作符给更深次的对象进行赋值,比如:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
...
this.setContextValue("member.setDesc", "xxxx");
...
}
}
同样的,你想调用指定上下文中的方法,也可以用上下文的前缀加以指定:
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
...
this.setContextValue("memberContext.member.setDesc", "xxxx");
...
}
}