210629-QlExpress使用姿势四:Operator与Micro扩展

文章目录
  1. 1. 自定义Opeartor
  2. 2. OperatorBase
  3. 3. Mciro
  4. 4. 小结
  • II. 其他
    1. 1. 一灰灰Blog: https://liuyueyi.github.io/hexblog
    2. 2. 声明
    3. 3. 扫描关注
  • 本文将介绍QlExpress中自定义操作符Operator + Micro的使用姿势,通过扩展Operator,可以为规则脚本赋能,提供更友好的使用姿势

    1. 自定义Opeartor

    通常需要实现一个自定义的Operator时,可以考虑通过继承Opeartor类,实现executeInner方法

    如实现一个字符串拆分操作符 split

    1
    2
    # 字符串,根据英文逗号进行分隔
    "11,22,33" split ','

    要实现上面这种脚本的支持,首先是定义一个自定义的Split

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    /**
    * 字符串转列表
    */
    public static class Split extends Operator {
    @Override
    public Object executeInner(Object[] objects) {
    // 第一个参数为String,第二个参数为分割符号
    String base = String.valueOf(objects[0]);
    String dot = ",";
    if (objects.length > 1) {
    dot = String.valueOf(objects[1]);
    }

    String[] cells = StringUtils.split(base, dot);
    java.util.List<String> result = new java.util.ArrayList<>();
    for (int i = 0; i < cells.length; i++) {
    String cell = cells[i].trim();
    if (cell.length() == 0) {
    continue;
    }
    result.add(cell);
    }
    return result;
    }
    }

    接下来注册Operator

    1
    2
    3
    4
    5
    6
    7
    ExpressRunner expressRunner = new ExpressRunner();
    DefaultContext<String, Object> context = new DefaultContext<>();
    expressRunner.addOperator("split", new Split());

    // 自定义Operator -> split, 实现字符串拆分为列表
    Object ans = expressRunner.execute("\"1,2,3,4,5\" split ','", context, null, true, false);
    System.out.println(ans);

    执行之后输出结果如下

    1
    [1, 2, 3, 4, 5]

    从上面Operator的实现可以看到,第二个参数不传时,默认采用英文逗号进行分隔,那么表达式应该怎么写呢?

    1
    2
    3
    // 下面两种写法都会抛异常
    expressRunner.execute("split '1,2,3,'", context, null, true, false);
    expressRunner.execute("'1,2,3,' split", context, null, true, false)

    目前从有限的使用姿势获取渠道上,使用Operator时,左右参数都需要有

    当然如果只需要传入一个参数时,可以考虑下面的方式

    注册Operator为方法

    1
    2
    3
    // 将Operator定义为function
    expressRunner.addFunction("splitFunc", new Split());
    System.out.println(expressRunner.execute("splitFunc(\"1,2,3,4,,5,\")", context, null, true, false));

    上面有拆分,接下来添加一个配套的Joiner

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /**
    * 列表转String
    */
    public static class Join extends Operator {

    @Override
    public Object executeInner(Object[] list) throws Exception {
    List target = (List) list[0];
    String dot = ",";
    if (list.length > 1) {
    dot = String.valueOf(list[1]);
    }

    return Stream.of(target).map(String::valueOf).collect(Collectors.joining(dot));
    }
    }

    测试case

    1
    2
    3
    4
    5
    6
    7
    8
    // 添加Join
    expressRunner.addOperator("join", new Join());
    expressRunner.addFunction("joinFunc", new Join());
    List list = Arrays.asList("hello", 1, 2, 3, "world");
    context.put("list", list);

    System.out.println("join:" + expressRunner.execute("list join ','", context, null, true, false));
    System.out.println("joinFunc:" + expressRunner.execute("joinFunc(list, \";\")", context, null, true, false));

    输出结果如

    1
    2
    join:[hello, 1, 2, 3, world]
    joinFunc:[hello, 1, 2, 3, world]

    2. OperatorBase

    自定义Operator除了上面这种姿势之外,还可以通过继承OperatorBase来实现更富有想象力的玩法

    比如实现一个编辑上下文信息的Operator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class OperatorContextPut extends OperatorBase {
    public OperatorContextPut(String aName) {
    this.name = aName;
    }

    @Override
    public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception {
    String key = list.get(0).toString();
    Object value = list.get(1);
    parent.put(key, value);
    return null;
    }
    }

    通过上面这个来实现编辑上下文内容(当然也是可以直接通过变量赋值,来修改上下文)

    3. Mciro

    宏定义,学过c的小伙伴多半不会陌生这个东西,QlExpress可以通过addMacro来实现宏定义

    如定义一个计数的宏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ExpressRunner runner = new ExpressRunner();
    DefaultContext<String, Object> context = new DefaultContext<>();

    // 宏,表示计数
    runner.addMacro("计数", "cnt = map.get(key); cnt = cnt == null ? 1: cnt + 1; map.put(key, cnt);");

    Map<String, Object> map = new HashMap<>();
    map.put("kk", 10);
    context.put("map", map);
    runner.execute("String key = \"kk\"; 计数", context, null, true, false);
    context.put("key", "cc");
    runner.execute("计数", context, null, true, false);
    System.out.println("计数之后:" + map);

    上面这个计数非常有意思,表达式就是一个 计数, 就可以实现map中key对应的value自增+1

    如上面的输出结果如下

    1
    计数之后:{kk=11, cc=1}

    4. 小结

    本文主要介绍QlExpress中自定义Operator的使用姿势,以及Micro宏的简单示例

    对于Opeartor,可以注册为Operator操作符,也可以注册为function;需要注意的是命名需要全局唯一

    系列博文:

    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

    ×