【TL】QLExpress
文章目录
- 1、快速开始
- 2、扩展Operator的使用
- 2.1 自定义Operator
- 2.2 使用Operator
- 3、绑定java类或者对象的method
- 4、macro 宏定义(规则执行)
- 5、java class的相关api
- 6、扩展Context
- 6.1、扩展IExpressContext
- 6.2、可以直接使用Spring容器托管的对象
- 7、自定义函数操作符获取原始的context控制上下文
- 相关文章
1、快速开始
<dependency><groupId>com.alibaba</groupId><artifactId>QLExpress</artifactId><version>3.2.0</version>
</dependency>
语法上QLExpress与java是十分类似的,具体看github的帮助文档
2、扩展Operator的使用
2.1 自定义Operator
继承com.ql.util.express.Operator实现executeInner即可
public static class JoinOperator extends Operator {@Overridepublic Object executeInner(Object[] list) throws Exception {Object operator1 = list[0];Object operator2 = list[1];if (operator1 instanceof List && operator2 != null) {((List) operator1).add(operator2);return operator1;} else if (operator2 != null) {List result = new ArrayList<>();result.add(operator1);result.add(operator2);return result;} else {return null;}}
}
2.2 使用Operator
方法 | 说明 |
---|---|
runner.addOperatorWithAlias() | 重命名操作符 |
runner.addOperator() | 添加操作符 |
runner.replaceOperator() | 替换操作符 |
runner.addFunction() | 添加方法 |
//添加操作符号,可以设置优先级
void addOperator(String name,Operator op);
void addOperator(String name,String aRefOpername,Operator op);//替换操作符处理
OperatorBase replaceOperator(String name,OperatorBase op);//添加操作符和关键字的别名,比如 if..then..else -> 如果。。那么。。否则。。
void addOperatorWithAlias(String keyWordName, String realKeyWordName,String errorInfo);
public static void main(String[] args) throws Exception {// 1、重命名操作符ExpressRunner runner = new ExpressRunner();DefaultContext<String, Object> context = new DefaultContext<>();runner.addOperatorWithAlias("大于", ">", null);System.out.println("1、重命名操作符;" + runner.execute("2 大于 1", context, null, true, false));// 2、添加操作符runner.addOperator("加入", new JoinOperator());System.out.println("2、添加操作符;" + runner.execute("1 加入 2 加入 3", context, null, true, false));// 3、替换操作符runner.replaceOperator("+", new JoinOperator());System.out.println("3、替换操作符;" + runner.execute("2 + 1", context, null, true, false));// 4、添加方法runner.addFunction("添加",new JoinOperator());System.out.println("4、添加方法;" + runner.execute("添加(1,2)", context, null, true, false));
}
3、绑定java类或者对象的method
方法 | 说明 |
---|---|
OperatorBase getFunciton(String name); | 通过name获取function的定义 |
runner.addFunctionOfClassMethod() | 绑定类方法 |
runner.addFunctionOfServiceMethod() | 绑定实例方法 |
//通过name获取function的定义
OperatorBase getFunciton(String name);//通过自定义的Operator来实现类似:fun(a,b,c)
void addFunction(String name, OperatorBase op);
//fun(a,b,c) 绑定 object.function(a,b,c)对象方法
void addFunctionOfServiceMethod(String name, Object aServiceObject,String aFunctionName, Class<?>[] aParameterClassTypes,String errorInfo);
//fun(a,b,c) 绑定 Class.function(a,b,c)类方法
void addFunctionOfClassMethod(String name, String aClassName,String aFunctionName, Class<?>[] aParameterClassTypes,String errorInfo);
//给Class增加或者替换method,同时 支持a.fun(b) ,fun(a,b) 两种方法调用
//比如扩展String.class的isBlank方法:“abc”.isBlank()和isBlank("abc")都可以调用
void addFunctionAndClassMethod(String name,Class<?>bindingClass, OperatorBase op);
public static void main(String[] args) throws Exception {ExpressRunner runner = new ExpressRunner();DefaultContext<String, Object> context = new DefaultContext<>();context.put("name", "张三");runner.addFunctionOfClassMethod("打印", Demo.class.getName(), "print", new Class[]{String.class}, null);runner.execute("打印(name)", context, null, true, false);runner.addFunctionOfServiceMethod("实例打印", new Demo(), "print2", new Class[]{String.class}, null);runner.execute("实例打印(name)", context, null, true, false);}public static class Demo {public static void print(String name) {System.out.println("1、静态方法打印:" + name);}public void print2(String name) {System.out.println("2、实例方法打印:" + name);}
}
4、macro 宏定义(规则执行)
方法 | 说明 |
---|---|
runner.addMacro() | 添加宏定义 |
//比如addMacro("天猫卖家","userDO.userTag &1024 ==1024")
void addMacro(String macroName,String express)
public static void main(String[] args) throws Exception {ExpressRunner runner = new ExpressRunner();DefaultContext<String, Object> context = new DefaultContext<>();context.put("数学", 93);context.put("语文", 65);context.put("英语", 60);runner.addMacro("平均值", "(数学+语文+英语)/3");runner.addMacro("是否平均及格", "平均值>60");System.out.println("1、平均值:" + runner.execute("平均值", context, null, true, false));System.out.println("2、是否平均及格:" + runner.execute("是否平均及格", context, null, true, false));
}
5、java class的相关api
方法 | 说明 |
---|---|
runner.addClassField() | 添加属性 |
runner.addClassMethod | 添加方法 |
注意,这些类的字段和方法是执行器通过解析语法执行的,而不是通过字节码增强等技术,所以只在脚本运行期间生效,不会对jvm整体的运行产生任何影响,所以是绝对安全的。
//添加类的属性字段
void addClassField(String field,Class<?>bindingClass,Class<?>returnType,Operator op);//添加类的方法
void addClassMethod(String name,Class<?>bindingClass,OperatorBase op);
public static void main(String[] args) throws Exception {ExpressRunner runner = new ExpressRunner();DefaultContext<String, Object> context = new DefaultContext<>();runner.addClassField("name", Demo.class, String.class, new Operator() {@Overridepublic Object executeInner(Object[] list) throws Exception {return "张三";}});runner.addClassMethod("print", Demo.class, new Operator() {@Overridepublic Object executeInner(Object[] list) throws Exception {System.out.println("2、设置方法:" + String.valueOf(list[1]));return null;}});String expStr = "demo = new com.zugou.test.Demo(); return demo.name;";System.out.println("1、设置属性:" + runner.execute(expStr, context, null, true, false));expStr = "demo = new com.zugou.test.Demo(); return demo.print(demo.name);";runner.execute(expStr, context, null, true, false);
}
6、扩展Context
上下文参数 IExpressContext context 非常有用,它允许put任何变量,然后在脚本中识别出来。
6.1、扩展IExpressContext
public class SpringExpressContext extends HashMap<String, Object> implements IExpressContext<String, Object> {private ApplicationContext context;public SpringExpressContext(ApplicationContext context) {// 用来保存Spring的上线问对象this.context = context;}public SpringExpressContext(Map<String, Object> map, ApplicationContext context) {super(map);this.context = context;}@Overridepublic Object get(Object key) {Object result = null;result = super.get(key);if (result == null && this.context != null && this.context.containsBean((String) key)) {result = this.context.getBean((String) key);}return result;}@Overridepublic Object put(String key, Object value) {return super.put(key, value);}public static class ApplicationContext {// 模拟Spring的上线文对象private static ConcurrentMap<String, Object> cache = new ConcurrentHashMap<>(12);private static ApplicationContext context = new ApplicationContext();public static ApplicationContext create() {// 模拟将对象加载到容器内context.putBean("userDto", new SpringExpress.UserDto("张三", 18));return context;}public boolean containsBean(String name) {return cache.containsKey(name);}public Object getBean(String name) {return cache.get(name);}public Object putBean(String name, Object object) {cache.put(name, object);return object;}}
}
6.2、可以直接使用Spring容器托管的对象
public static void main(String[] args) throws Exception {ExpressRunner runner = new ExpressRunner();SpringExpressContext context = new SpringExpressContext(SpringExpressContext.ApplicationContext.create());context.put("nick", "李四");String exp = "userDto.setName(nick);return userDto.getName();";System.out.println(runner.execute(exp, context, null, true, false));
}public static class UserDto {String name;Integer age;public UserDto(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}
7、自定义函数操作符获取原始的context控制上下文
让自定义的Operator继承OperatorBase即可,通过parent来获取context的上下文对象
public class SpringOperator extends OperatorBase {@Overridepublic OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception {Object obj = parent.get(String.valueOf(parent.get(String.valueOf(list.get(0)))));String method = (String) parent.get(String.valueOf(list.get(1)));System.out.println("测试Operator方法:" + method);Method[] methods = obj.getClass().getMethods();for (Method _method : methods) {if (_method.getName() == method) {return new OperateData(_method.invoke(obj, null), _method.getReturnType());}}return null;}
}
public static void main(String[] args) throws Exception {ExpressRunner runner = new ExpressRunner();runner.addFunction("执行容器中Bean的方法", new SpringOperator());SpringExpressContext context = new SpringExpressContext(SpringExpressContext.ApplicationContext.create());context.put("参数1", "userDto");context.put("参数2", "getName");String exp = "执行容器中Bean的方法(参数1,参数2)";System.out.println(runner.execute(exp, context, null, true, false));
}
相关文章
GIT 地址
【TL】QLExpress相关推荐
- 【TL】【编码】瞬间移动-百度之星初赛(Astar Round2B)1003-2016.05.22
瞬间移动 Accepts: 1018 Submissions: 3620 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/6553 ...
- OpenCV 【七】————边缘提取算子(图像边缘提取)——canny算法的原理及实现
canny边缘检测实现(C++.opencv) 1.作用: 图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波.我们知道微分运算是求信号的变化率,具有加强高频分量的作用.在空域运 ...
- 如何保证两个不同宽高的canvas用同一组坐标正常显示_如何1人5天开发完3D数据可视化大屏 【一】...
相信从事过数据可视化开发的你对大屏并不陌生,那么开发一个酷炫的大屏一定是很多数据可视化开发者想要做的事情. 我们使用three.js,大约一周的时间开发出了一个酷炫的数据可视化大屏: 1. 前言 由于 ...
- 【其它】我博客的个性化代码
[代码]今天有很多人来问我要那些宠物什么的代码,今天一并给大家. [页面定制CSS代码] #google_ad_c1,#div-gpt-ad-1320933818841-0,#google_ad_c2 ...
- 【20161109】noip模拟赛
1.Game [题目描述] 明明和亮亮在玩一个游戏.桌面上一行有n个格子,一些格子中放着棋子.明明和亮亮轮流选择如下方式中的一种移动棋子(图示中o表示棋子,*表示空着的格子): 1) 当一枚棋子的右边 ...
- 【采用】机器学习在金融大数据风险建模中的应用
本文在传统风险模型体系的基础上,嫁接逻辑回归和决策树模型建立T-L模型,并结合Random Forest模型完善模型结构.采用T-L核模型替代RF模型中的传统决策树模型,将RF模型和T-L核模型结合, ...
- 【NLP】【七】fasttext源码解析
2019独角兽企业重金招聘Python工程师标准>>> [一]关于fasttext fasttext是Facebook开源的一个工具包,用于词向量训练和文本分类.该工具包使用C++1 ...
- 【项目管理】上线切割计划实践
导读:系统版本上线发布前,中,后过程,引入CutoverPlan计划,即切割计划.特别是多个关联系统有依赖关系的情况,就需要统一对齐切割计划的每一个执行项和关注依赖项.在最近一个中台项目的大版本中有1 ...
- 【图像处理】——Python图像分割边缘检测算法之一阶梯度算子(Roberts、Prewitt、Sobel、 Kirsch、Canny算子)
目录 前言 一.边缘检测算法 1.一阶算子 2.二阶算子 二.一阶算子 原图像lena 1.Roberts算子 不同方向的算子模板 梯度的计算 系统代码: 自定义函数代码 结果 2.Prewitt 不 ...
最新文章
- mybatis动态查询列名,#与¥
- Log4j的简单配置使用
- Know Difference between Oracle Reserved Words and Keywords
- testbed笔记:头文件里的函数
- freenas搭建nas及san网络存储详解
- 交通守护者“电子警察”
- 蛮力法 第4关:韩信点兵问题
- 近来开发工作不忙,零零散散整理的Java基础
- Tair ldb(leveldb存储引擎)实现介绍
- 验证sqlserver 2000 sp4补丁是否安装成功(安装补丁后可以远程访问)
- 未检测到与wia兼容的设备_为不支持 WIA 的设备配置基于 intranet 窗体的身份验证...
- 三大运营商的网上流量卡数据对比,看看你会选哪一个?
- 键盘大小写切换时小写shift和大写caps Lock按键问题
- SAP 今年上半年的业绩非常
- 修复之前写的模拟I2C程序,增加多总线,时序更精确操作
- CSS 实现DIV水平垂直居中(一)
- 从0开始集成Spring和mybatis
- android setdata方法,Android intent.setData方法
- 佳博打印机android版本代码优化
- 30条经典的SQL语句
热门文章
- EXCEL通过配置导入规则,实现任意格式EXCEL文件解析
- CANoe系列教程-分析窗口-State Tracker
- Python读取数据库数据写入Excel
- 前端之javascript的节点操作和Event
- JAVA删除Cookie
- 解决:UnicodeDecodeError: 'gbk' codec can't decode byte 0x8b in position 21804: illegal multibyte seque
- 【开发教程2】开源蓝牙心率防水运动手环-套件检测教程
- 微信qq拦截检测易语言代码
- 直播流程以及常见问题
- tokudb 分形树_TokuDB存储引擎