QLExpress使用问题

来源:互联网 发布:linux c 多线程编程 编辑:程序博客网 时间:2024/06/05 11:01

QLExpress在Java&Scala中使用问题

需求: 简单的规则引擎(支持四则运算),scala 下运行。先尝试在java下测试demo。

  • 资料
    artifact :
    <dependency>
    <groupId>com.taobao.util</groupId>
    <artifactId>taobao-express</artifactId>
    <version>3.0.17</version>
    </dependency>

    github : https://github.com/alibaba/QLExpress

  • jar使用问题

    官方仓库 http://maven.aliyun.com/nexus/content/repositories/public 下找不到的该jar;
    在项目提供的mvn地址 http://mvnrepo.alibaba-inc.com/mvn 也无法打开。

下面就需要本地去尝试做mvn deploy。
1. 在github下载源码后解压到IDEA,
2. mvn compile 可以编译成功
mvn package 错误,BUILD FAILURE。

[ERROR] /C:/Users/.../QLExpress-master/src/test/java/com/ql/util/express/test/AClassDefineSingle.java:[12,40] unmappable character for encoding GBK

很明显由于IDE设置的encoding : utf-8, 而该项目应该是gbk的。
下一步去修改项目的编码-> GBK。
3.重新设置GBK(注意这里项目中文件可能存在多种编码)后, 会发现很多单元测试异常,依然无法通过打包。
4.放弃完整打包, 即只打包源码, 跳过项目的test阶段,需要加上-DskipTests

    mvn package -Dmaven.test.skip=true  

最后得到这个jar,可以选择丢在本地仓库, 或者用deploy丢到nuxus的远程库上面去, 在使用maven去引用它!
5. 测试:

public class Test {    public static void main(String[] args) throws Exception{        String express = "10 * 10 + 1 + 2 * 3 + 5 * 2";        ExpressRunner runner = new ExpressRunner(false,true);        Object r = runner.execute(express,null, null, true,true);        System.out.println("表达式计算:" + express + " = " + r);    }}

这里写图片描述

附scala的运行结果:

scalaVersion := "2.10.4"sbtVersion := "1.0.3"

因为我的qlexpress丢在了公司的库上面, 所以必须申明一下:

libraryDependencies += "com.taobao.util" % "taobao-express" % "3.1.7"resolvers += " Maven Repository [nexus]        " at "http://192.168.9.200:8002/nexus/content/groups/public/"

demo :

import com.ql.util.express.ExpressRunner/**  *  *  * @author michael  * @version 1.0 Created on 2017/12/19 12:11  */object QlDemo {  def main(args: Array[String]): Unit = {    val express = "10 * 10 + 1 + 2 * 3 + 5 * 2"    val runner = new ExpressRunner(false, true)    val r = runner.execute(express, null, null, true, true)    System.out.println("表达式计算:" + express + " = " + r)  }}

这里写图片描述

以上, 解决了引用的问题。

下面进入正题, 使用scala来操作简单的四则运算:

val runner = new ExpressRunner(false, true)    var context = new DefaultContext[String, AnyRef]    context.put("a", 23)    val r = runner.executeFloat(express, context, null, true, false)    System.out.println("表达式计算: " + express + " = " + r)

那么这里的context在java中是一个HashMap《K,V》, 泛型的指向对象V在scala中则会自动转成AnyRef。
这里写图片描述
scala中的int、long 、 float等都继承AnyVal, 只有String继承AnyRef,所以上面的demo中无法实现。所以下面强制转换String尝试

val runner = new ExpressRunner()    var context = new DefaultContext[String, AnyRef]//    context+=("a"->null)      context.put("a", 1.toString)    context.put("a", 2.toString)    context.put("c", 3.toString)    val express: String = "a+b*c"    val r = runner.execute(express, context, null, true, false, null)    System.out.println("表达式计算: " + express + " = " + r)

ERROR: String转换Number异常

了解一下源码中的参数解析:

 * @param expressString 程序文本 * @param context 执行上下文 * @param errorList 输出的错误信息List * @param isCache 是否使用Cache中的指令集 * @param isTrace 是否输出详细的执行指令信息 * @param aLog 输出的log

Error原因: qlExpress在上下文代入时会把参数值强制转换为Number, 因为scala的语言这里把数值内容包装成String,所以转换异常。

解决: 修改源码OperatorOfNumber.java(进入qlexpress项目中)

a.将文件中的所有 (Number)op1,(Number)op2 修改为new BigDecimal(op1.toString()),new BigDecimal(op2.toString())
例如:

修改前->PreciseNumberOperator.addPrecise((Number)op1,(Number)op2)
修改后->PreciseNumberOperator.addPrecise(new BigDecimal(op1.toString()),new BigDecimal(op2.toString()))

b. qlExpress对字符内容的 + 运算有特殊处理, 这里需要修改

public static Object add(Object op1, Object op2,boolean isPrecise) throws Exception {        if(op1 == null){            op1 = "null";        }        if(op2 == null){            op2 = "null";        }        //因为scala用字符串类型包装数据内容, 这里需要禁用//      if (op1 instanceof String || op2 instanceof String) {//          return op1.toString() + op2.toString();//      }        if(isPrecise==true){            return PreciseNumberOperator.addPrecise(new BigDecimal(op1.toString()),new BigDecimal(op2.toString()));        }else{            return NormalNumberOperator.addNormal(new BigDecimal(op1.toString()),new BigDecimal(op2.toString()));        }    }

修改完qlexpress, 重新打包测试

val runner = new ExpressRunner(false, true)    val express: String = "a+b*c-d/e"    var context1 = new DefaultContext[String, AnyRef]    var a: Any = 2.20    var b: Any = 2    var c: Any = 3    var d: Any = 3    var e: Any = 1    context1.put("a", a.toString)    context1.put("b", b.toString)    context1.put("c", c.toString)    context1.put("d", d.toString)    context1.put("e", e.toString)    val r1 = runner.execute(express, context1, null, true, true)    System.out.println("表达式计算: " + express + " = " + r1)
1:   STAT_BLOCK:STAT_BLOCK                                                          STAT_BLOCK2:      STAT_SEMICOLON:STAT_SEMICOLON   STAT_SEMICOLON3:         -:-  -4:            +:+   +5:               a:ID   ID5:               *:*    *6:                  b:ID    ID6:                  c:ID    ID4:            /:/   /5:               d:ID   ID5:               e:ID   ID表达式计算: a+b*c-d/e = 5.2Process finished with exit code 0

测试通过!

原创粉丝点击