210628-QlExpress使用姿势三:Function与方法绑定

文章目录
  1. 1. 自定义Function
  2. 2. 类方法绑定
  3. 3. 实例方法绑定
  4. 4. 小结
  • II. 其他
    1. 1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
    2. 2. 声明
    3. 3. 扫描关注
  • 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<>();

    // 脚本定义function
    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方法

    那么如果我们希望复用方法,可以怎么做呢?

    • 绑定Java方法

    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();
    }

    // 对于jdk1.8,可以直接使用Stream来实现等价于上面的拼接功能
    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
    // 注意不定参数,如果需要按照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);

    输出结果

    1
    绑定对象方法:[a, b, c, d]

    4. 小结

    本文主要介绍了QlExpress的方法扩展,支持在脚本中,通过function定义函数,实现调用,

    • 注意:这种函数的生命周期是当前脚本

    其次可以通过绑定静态类方法 + 实例方法,让脚本可以直接调用Java相关方法,实现功能扩展

    • 注意:方法名需要全局唯一

    QlExpress系列教程

    II. 其他

    1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

    一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

    2. 声明

    尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

    3. 扫描关注

    一灰灰blog

    QrCode

    评论

    Your browser is out-of-date!

    Update your browser to view this website correctly. Update my browser now

    ×