QlExpress绑定方法,实现能力扩展;支持自定Function,再脚本中定义函数,实现复用
1. 自定义Function QlExpress支持在脚本中定义函数(等同于java中的方法),主要利用关键字function
来修饰
一个简单的case如下
1 2 3 4 5 6 7 8 9 function add (int a, int b) { return a + b; } function sub (int a, int b ) { return a - b; } return add(10 , 20 ) + sub(4 , 2 );
上面定义了两个方法,一个add
, 一个sub
,需要注意的是与Java不同点在于无需定义返回类型
访问case如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ExpressRunner runner = new ExpressRunner(); DefaultContext<String, Object> context = new DefaultContext<>(); String express = "function add(int a, int b) {\n" + " return a + b;\n" +"}\n" +"\n" +"function sub(int a, int b ) {\n" +" return a - b;\n" +"}\n" +"\n" +"return add(10, 20) + sub(4, 2);" ;System.out.println(runner.execute(express, context, null , true , false )); System.out.println(runner.execute("add(11, 22)" , context, null , true , false ));
输出如下
1 2 3 4 5 6 7 32 [main] ERROR com.ql.util.express.InstructionSet - 当前ProgramPoint = 2 [main] ERROR com.ql.util.express.InstructionSet - 当前指令call Function[add] OPNUMBER[2] [main] ERROR com.ql.util.express.InstructionSet - java.lang.Exception: run QlExpress Exception at line 1 :在Runner的操作符定义和自定义函数中都没有找到"add"的定义 Exception in thread "main" java.lang.Exception: run QlExpress Exception at line 1 :在Runner的操作符定义和自定义函数中都没有找到"add"的定义 at com.ql.util.express.instruction.detail.InstructionCallSelfDefineFunction.execute(InstructionCallSelfDefineFunction.java:62) at com.ql.util.express.InstructionSet.executeInnerOrigiInstruction(InstructionSet.java:204)
在第一个脚本中定义的function,在同一脚本中访问可以;
但是需要注意这个function并不是通用的,所以上面第二个脚本执行add(11,22)
会提示没有add
方法
那么如果我们希望复用方法,可以怎么做呢?
2. 类方法绑定 在类 FunctionDemo
中添加一个静态方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static String join (Object... obj) { StringBuilder builder = new StringBuilder(50 ); for (Object o : obj) { if (builder.length() > 0 ) { builder.append("," ); } builder.append(o); } return builder.toString(); } public static String join (Object... obj) { return Stream.of(obj).map(String::valueOf).collect(Collectors.joining("," )); }
静态方法的绑定比较简单,直接使用addFunctionOfClassMethod
,如下
1 2 runner.addFunctionOfClassMethod("join", FunctionDemo.class.getName(), "join", new Class[]{Object[].class}, null);
第一个参数 join
表示绑定之后的方法命名(注意全局唯一)
第二个参数为类名
第三个参数为类方法名
第四个参数为类方法参数类型(因为是不定长参数,所以是new Class[]{Object[].class}
)
第五个参数为异常信息
使用姿势如下
1 2 3 4 5 6 7 8 9 10 11 12 13 Object ans = runner.execute("join([\"hello\", \"一灰灰\", \"blog\"])" , context, null , true , false ); System.out.println("静态方法调用:" + ans); ``` 重点关注上面的表达式,传参是 `["hello" , "一灰灰" , "blog" ]`,是一个数组形式的,与java中不定长参数的访问姿势不同 如果我希望象Java中一样,也支持不定长传参姿势,可以如下配置 ```java DynamicParamsUtil.supportDynamicParams = true ; ans = runner.execute("join(\"hello\", \"一灰灰\", \"blog\")" , context, null , true , false ); System.out.println("静态方法调用:" + ans);
输出结果
1 2 静态方法调用:hello,一灰灰,blog 静态方法调用:hello,一灰灰,blog
说明
3. 实例方法绑定 除了静态方法绑定之外,也可以绑定实例方法,使用姿势与上面基本一致,只是调用的是addFunctionOfServiceMethod
而已
添加一个实例方法
1 2 3 4 public List<String> split (String text) { String[] cells = text.split("," ); return Arrays.asList(cells); }
然后测试case如下
1 2 3 4 5 6 FunctionDemo functionDemo = new FunctionDemo(); runner.addFunctionOfServiceMethod("split" , functionDemo, "split" , new Class[]{String.class }, null ) ; context.put("list" , "a,b,c,d" ); ans = runner.execute("split(list)" , context, null , true , false ); System.out.println("绑定对象方法:" + ans);
输出结果
4. 小结 本文主要介绍了QlExpress的方法扩展,支持在脚本中,通过function
定义函数,实现调用,
其次可以通过绑定静态类方法 + 实例方法,让脚本可以直接调用Java相关方法,实现功能扩展
QlExpress系列教程
II. 其他 一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
3. 扫描关注 一灰灰blog