本文将介绍QlExpress中自定义操作符Operator + Micro的使用姿势,通过扩展Operator,可以为规则脚本赋能,提供更友好的使用姿势
1. 自定义Opeartor 通常需要实现一个自定义的Operator时,可以考虑通过继承Opeartor类,实现executeInner方法
如实现一个字符串拆分操作符 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 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());   Object ans = expressRunner.execute("\"1,2,3,4,5\" split ','" , context, null , true , false ); System.out.println(ans); 
执行之后输出结果如下
从上面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 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 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 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
如上面的输出结果如下
4. 小结 本文主要介绍QlExpress中自定义Operator的使用姿势,以及Micro宏的简单示例
对于Opeartor,可以注册为Operator操作符,也可以注册为function;需要注意的是命名需要全局唯一
系列博文: 
II. 其他 一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明 尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
3. 扫描关注 一灰灰blog