当前位置:  软件>java软件

java表达式计算 QLExpress

    来源:    发布时间:2015-02-01

    本文导语:   @author qhlhl2010@gmail.com  你想知道   a love b = ? 吗 ,你想随意定义自己的操作符号吗 ? 请使用 QLExpress工具包 QLExpress 是一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用。让业务规则定义简便而...

 @author qhlhl2010@gmail.com

 你想知道   a love b = ? 吗 ,你想随意定义自己的操作符号吗 ? 请使用 QLExpress工具包

QLExpress 是一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用。让业务规则定义简便而不失灵活。让业务人员就可以定义业务规则。支持标准的JAVA语法,还可以支持自定义操作符号、操作符号重载、 函数定义、宏定义、数据延迟加载等。 

这个表达式相对别的计算工具,优点主要体现在:
      A、不需要预先加载可能需要的所有属性值
      B、 用户可以根据业务需要自定义操作符号和函数
      C、可以同步输出判断错误信息,有利于提高业务系统在规则判断等使用场景下的用户体验。减少业务系统相关的处理代码。
    
       主要用途:一些业务规则的组合判断,同时需要输出相关的错误信息
  
   执行的流程:
   1、单词分解
   2、语法分析
 
  最简单Hello范例:
 
   String express = "10 * 10 + 1 + 2 * 3 + 5 * 2";
   ExpressRunner runner = new ExpressRunner();
   Object result = runner.execute(express, null, false, null);
   System.out.println("表达式计算:" + express + " = " + result);
 
  其它范例:
   ExpressRunner runner = new ExpressRunner();
  runner.addOperator("love", new LoveOperator("love"));
  runner.addOperatorWithAlias("属于", "in", "用户$1不在允许的范围");
  runner.addOperatorWithAlias("myand", "and", "用户$1不在允许的范围");
  runner.addFunction("累加", new GroupOperator("累加"));
  runner.addFunction("group", new GroupOperator("group"));
  runner.addFunctionOfClassMethod("isVIP", BeanExample.class.getName(),
    "isVIP", new String[] { "String" }, "$1不是VIP用户");
  runner.addFunctionOfClassMethod("取绝对值", Math.class.getName(), "abs",
    new String[] { "double" }, null);
  runner.addFunctionOfClassMethod("转换为大写", BeanExample.class.getName(),
    "upper", new String[] { "String" }, null); 

      在这个计算引擎里面, 执行下述表达式结果:
       Example 0 : System.out.println("ss") =  null
       Example 1 : unionName = new com.ql.util.express.test.BeanExample("张三").unionName("李四") =  张三-李四
       Example 2 : group(2,3,4) =  9
       Example 3 : 取绝对值(-5.0) =  5.0
       Example 4 : max(2,3,4,10) =  10
       Example 5 :  max(3,2) + 转换为大写("abc") =  3ABC
       Example 6 :  c = 1000 + 2000 =  3000
       Example 7 : b = 累加(1,2,3)+累加(4,5,6) =  21
       Example 8 : 三星卖家 and 消保用户  =  true
       Example 9 : 'a' love 'b' love 'c' love 'd' =  d{c{b{a}b}c}d
       Example 10 :  10 * 10 + 1 + 2 * 3 + 5 * 2 =  117
       Example 11 :  ( (1+1) 属于 (4,3,5)) and isVIP("玄难") =  false
         系统输出的错误提示信息:[用户 2 不在允许的范围,  玄难 不是VIP用户]
      
 
  表达式支持概述:
  1、基本的java语法:
    A、四则运算 : 10 * 10 + 1 + 2 * 3 + 5 * 2
   B、boolean运算: 3 > 2 and 2 > 3
     C、创建对象,对象方法调用,静态方法调用:new com.ql.util.express.test.BeanExample("张三").unionName("李四")
     D、变量赋值:a = 3 + 5
     F、支持 in,max,min:  (a in (1,2,4)) and (b in("abc","bcd","efg"))
  2、提供表达式上下文,属性的值不需要在初始的时候全部加入,
     而是在表达式计算的时候,需要什么信息才通过上下文接口获取
     避免因为不知道计算的需求,而在上下文中把可能需要的数据都加入。
     runner.execute("三星卖家 and 消保用户",errorList,true,expressContext)
     "三星卖家"和"消保用户"的属性是在需要的时候通过接口去获取。
  3、可以将计算结果直接存储到上下文中供后续业务使用。例如:
        runner.execute("c = 1000 + 2000",errorList,true,expressContext);
        则在expressContext中会增加一个属性c=3000,也可以在expressContext实现直接的数据库操作等。
  4、 可以将类和Spring对象的方法映射为表达式计算中的别名,方便其他业务人员的立即和配置。例如:
     将 Math.abs() 映射为 "取绝对值"。 则  "取绝对值(-5.0)" = "5.0"
     runner.addFunctionOfClassMethod("取绝对值", Math.class.getName(), "abs",new String[] { "double" }, null);
  5、可以为已经存在的boolean运算操作符号设置别名,增加错误信息同步输出,在计算结果为false的时候,同时返回错误信息。例如:
     runner.addOperatorWithAlias("属于", "in", "用户$1不在允许的范围")。
     用户自定义的函数同样也可以设置错误信息:例如:
   runner.addFunctionOfClassMethod("isOk", BeanExample.class.getName(),"isOk", new String[] { "String" }, "$1 不是VIP用户");
 
     则在调用List errorList = new ArrayList();
     Object result =runner.execute("( (1+1) 属于 (4,3,5)) and isOk("玄难")",errorList,true,null);
      执行结果 result = false.同时在errorList中还会返回2个错误原因:
       1、"用户 2 不在允许的范围",2、玄难 不是VIP用户  
     这在业务系统需要进行规则计算,同时需要返回
   
  6、可以自定义计算函数。例如:
     自定一个操作函数 group:
 class GroupOperator extends Operator {
 public GroupOperator(String aName) {
  this.name= aName;
 }
 public Object executeInner(Object[] list)throws Exception {
  Object result = new Integer(0);
  for (int i = 0; i < list.length; i++) {
   result = OperatorOfNumber.Add.execute(result, list[i]);
  }
  return result;
 }
 }
          然后增加到运算引擎:
     runner.addFunction("累加", new GroupOperator("累加"));
  runner.addFunction("group", new GroupOperator("group"));
          则 执行:group(2,3,4)  = 9 ,累加(1,2,3)+累加(4,5,6)=21
  7、可以自定义新的操作符号  。自定义的操作符号优先级设置为最高。例如 :
    自定一个操作函数 love:
class LoveOperator extends Operator { 
 public LoveOperator(String aName) {
  this.name= aName;
 }
 public Object executeInner(Object[] list)
   throws Exception {
  String op1 = list[0].toString();
  String op2 = list[1].toString();
  String result = op2 +"{" + op1 + "}" + op2;  
  return result;
 }
}
         然后增加到运算引擎:
      runner.addOperator("love", new LoveOperator("love"));
        则 执行:'a' love 'b' love 'c' love 'd' = "d{c{b{a}b}c}d"
  8、运算引擎在没有预编译的情况下, 执行10万次  "10 * 10 + 1 + 2 * 3 + 5 * 2" 耗时:3.187秒
             runner.execute("10 * 10 + 1 + 2 * 3 + 5 * 2", null, false,null);
            在打开 预编译缓存开关的情况下, 执行10万次 "10 * 10 + 1 + 2 * 3 + 5 * 2" 耗时:  0.171秒
             runner.execute("10 * 10 + 1 + 2 * 3 + 5 * 2", null, true,null);      
            运行引擎是线程安全的。在业务系统中实际使用过程中应该打开缓存预编译的开关,性能会更加。
             可以调用clearExpressCache()清除缓存 。
           在开启开关的情况下,会缓存解析后的最后执行指令如下所示,
           避免了字符串解析、词法分析、语法分析等步骤,简单对比一下,会提高30倍的速度:
 1:LoadData 10
  2:LoadData 10
  3:OP : * OPNUMBER[2]
  4:LoadData 1
  5:OP : + OPNUMBER[2]
  6:LoadData 2
  7:LoadData 3
  8:OP : * OPNUMBER[2]
  9:OP : + OPNUMBER[2]
  10:LoadData 5
  11:LoadData 2
  12:OP : * OPNUMBER[2]
  13:OP : + OPNUMBER[2]    
   9、这个表达式相对别的计算工具,有点主要体现在:
      A、不需要预先加载可能需要的所有属性值
      B、 用户可以根据业务需要自定义操作符号和函数
      C、可以同步输出判断错误信息,有利于提高业务系统在规则判断等使用场景下的用户体验。减少业务系统相关的处理代码。
   10、后续可以进一步优化的地方:
      A、现有的单词拆解、词法分析、语法分析都是自己写的山寨版,可以利用其他成熟的开源工具。
      B、优化具体的操作指令,提高单个操作符号的运行效率
      C、经过简单的扩展支持自定义代码片段的运行。   


    
 
 

您可能感兴趣的文章:

  • Java表达式引擎 Aviator
  • Java正则表达式 reb4j
  • Java表达式语言 JUEL
  • JAVA的类库中是否有正则表达式这样的东东?
  • Java表达式语法解析库 parboiled
  • Java表达式解析器 JExel
  • java 正则表达式基础,实例学习资料收集大全 原创
  • Java算术表达式计算类库 ExpressionJ
  • java正则表达式验证函数
  • java正则表达式获取url的host示例
  • java 公式解析 表达式解析 expression-analyzer
  • java正则表达式提取数字的方法实例
  • java正则表达式使用示例
  • java正则表达式验证邮箱、电话号码示例
  • java正则表达式应用的实例代码
  • Java的表达式计算引擎 Expr4J
  • java中 利用正则表达式提取( )内内容
  • 利用Java正则表达式校验邮箱与手机号
  • java正则表达式表单验证类工具类(验证邮箱、手机号码、qq号码等)
  • java正则表达式解析html示例分享
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java使用正则表达为数字添加千位符的简单方法
  • 在java中,如何表达界于20和40之间?
  • 请问 java.lang.Float x= new java.lang.Float(request.getParameter("x"))的表达正确吗
  • java使用正则表达校验手机号码示例(手机号码正则)
  • JAVA有没有这样的类,或怎么表达这样的数据?
  • Java8新特性之Lambda表达式浅析
  • java正则表达式匹配网页所有网址和链接文字的示例
  • 通过Java正则表达式去掉SQL代码中回车换行和多余空格
  • Java 正则表达式功能及应用
  • Java/Js下使用正则表达式匹配嵌套Html标签
  • Java 正则表达式 解释说明
  • Java8新特性lambda表达式有什么用(用法实例)
  • 收集的一些常用java正则表达式
  • Java中如何计算表达式
  • Java Lambda表达式详解和实例
  • Java的正则表达式深入分析
  • linux iis7站长之家
  • Java 正则表达式详解
  • java正则表达式彻底研究
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: stringflavor定义及介绍
  • 我对JAVA一窍不通,可惜别人却给我一个Java的project,要我做一个安装程序,请问哪里有JAVA INSTALLER下载,而且我要不要安装java的sdk才能完成此项任务?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3