前言
最近做一个功能需要把一个数学公式保存到数据库,然后通过java读取数学公式,传入参数进行计算,发现了java中的javax.script,它开始存在于JDK1.6,它可以解析通用的表达式,如三目,还可以利用js函数语法,创造一个就像java的函数一样存在于内存中随时可以被调用的函数,更可以将js中的对象直接转换成java对象。
script包
最主要的几个类和接口为:ScriptEngineManager,ScriptEngine,CompiledScript和Bindings
- ScriptEngineManager:是一个工厂的集合,可以通过name或者tag的方式获取某一个脚本的工厂,并且生成一个脚本的ScriptEngine.
ScriptEngine engine=new ScriptEngineManager().getEngineByName("JavaScript");
- ScriptEngine:是一个脚本引擎,包含一些操作方法,eval,createBindings,setBindings
engine.eval(option); //option:"10+((D-parseInt(D/28)*28)/7+1)*10";
option 可以是一段js代码,函数,函数传参需要调用 engine.createBindings获得bindings,bindings.put(key,value)来传入参数
- CompliedScript: engine 实现该接口,可以将ScriptEngine解析一段脚本的结果存起来,方便多次调用,需要将engine向上转换
Compilable compilable=(Compilable) engine;
CompiledScript JSFunction=compilable.compile(option); //解析编译脚本函数
Bindings bindings=engine.createBindings();
bindings.put(key,value);
JSFunction.eval(bingdings);
- Bindings:用来存放数据的容器,它有3个层级,为Global级、Engine级和Local级,前2者通过ScriptEngine.getBindings()获得,是唯一的对象,而Local Binding由ScriptEngine.createBindings()获得,很好理解,每次都产生一个新的。Global对应到工厂,Engine对应到ScriptEngine,向这2者里面加入任何数据或者编译后的脚本执行对象,在每一份新生成的Local Binding里面都会存在。
Demo
String option="function getNum(num){if(num%7==0){ return 5+5*(parseInt(5*(num-parseInt(num/29)*28)/28)+1)}else{return 5;}} getNum(num)"
-------------------------------
try{
Compilable compilable = (Compilable) engine;
Bindings bindings = engine.createBindings(); //Local级别的Binding
CompiledScript JSFunction = compilable.compile(option); //解析编译脚本函数
for(Map.Entry<String,Object> entry:map.entrySet()){
bindings.put(entry.getKey(),entry.getValue());
}
Object result=JSFunction.eval(bindings);
System.out.println(result);
return (int)Double.parseDouble(result.toString());
}catch (ScriptException e) {
e.printStackTrace();
}