Java详解ScriptEngine接口动态执行JS脚本
作者:Cavewang
大多的方法描述都来自于jdk11API帮助文档,由于是机翻,可能有些难以理解,大家多多担待
简介
首先来看一下JDK11API文档中对ScriptEngine的描述
模块 java.scripting
软件包 javax.script
Interface ScriptEngin
public interface ScriptEngine
ScriptEngine是基本接口,其方法必须在本规范的每个实现中完全起作用。
这些方法提供基本脚本功能。 写入这个简单接口的应用程序可以在每个实现中进行最少的修改。 它包括执行脚本的方法,以及设置和获取值的方法。
值是两种类型的键/值对。 第一类对包括其密钥在本说明书中保留和定义的那些或由各个实现组成。 具有保留键的对中的值具有指定的含义。
另一种类型的对包括那些创建Java语言绑定的对,这些值通常由脚本中的相应键或它们的装饰形式表示。
Eval(String script)
eval方法有多个重载,本文只介绍最常用的Eval(String script)
描述
执行指定的脚本。
实例代码
/** * ScriptEngine.eval() */ public void jsEngineEvalTest() { ScriptEngineManager sem = new ScriptEngineManager(); //查找并为给定的扩展创建ScriptEngine。也可用getEngineByName,查找并为给定名称创建ScriptEngine ScriptEngine jsEngine = sem.getEngineByExtension("js"); try { jsEngine.eval("var array = [1, 2, 3, 4, 5];for (var i = 0; i < array.length; i++) {print('index:' + i + ',value:' + array[i]);}"); } catch (ScriptException e) { e.printStackTrace(); } }
执行的脚本很简单,遍历输出了一个数组
结果如下所示:
index:0,value:1
index:1,value:2
index:2,value:3
index:3,value:4
index:4,value:5
Put() and Get()
描述
void put(String key, Object value) : 设置ScriptEngine状态中的键/值对,可以创建用于执行脚本的Java语言绑定,也可以以其他方式使用,具体取决于是否保留键。
Object get(String key) : 检索在此引擎状态下设置的值。 该值可能是其中之一是使用设置setValue或状态的其他值ScriptEngine ,取决于实施。
实例代码
/** * ScriptEngine.put() and ScriptEngine.get() */ public void jsEnginePutTest(){ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); //向engine中存值 engine.put("str", "jsEnginePutTest"); try { engine.eval("var output ='' ;for (i = 0; i <= str.length; i++) { output = str.charAt(i) + output }"); } catch (ScriptException e) { e.printStackTrace(); } //从engine中取值 String name = (String) engine.get("output"); System.out.println("被翻转后的字符串:"+name); }
此处的js脚本是将str字符串进行翻转操作,结果如下
被翻转后的字符串:tseTtuPenignEsj
CompiledScript
描述
通过存储编译结果的类进行扩展。 状态可以以Java类,Java类文件或脚本语言操作码的形式存储。 脚本可以重复执行而无需重新分析。
我的理解:将ScriptEngine解析一段脚本的结果存起来,方便多次调用。但是使用时要先将ScriptEngine用Compilable接口强制转换,然后调用compile(String script)方法就能返回一个CompiledScript对象,下次使用的时候调用一下CompiledScript.eval()即可,以此可以省略每次使用脚本都要重新解析一遍的过程。
实例代码
/** * CompiledScript */ public void compiledScriptTest(){ ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("javascript"); //进行强制转换 Compilable compilable = (Compilable) engine; String script = "print('CompiledScriptTest')"; try { //脚本解析结果存到JSFunction中,下次使用时用jsFunction.eval()即可 CompiledScript jsFunction = compilable.compile(script); jsFunction.eval(); } catch (ScriptException e) { e.printStackTrace(); } }
此处js脚本只是进行一个简单的输出,结果如下:
CompiledScriptTest
Bindings
描述
没有找到对Bindings很准确的解释,这里写下查阅了很多码友的笔记后我的得出的结论,Bindings是一个用来存放数据的容器,它有3个层级,为Global级、Engine级和Local级,前2者通过ScriptEngine.getBindings()获得,是唯一的对象,而Local Binding由ScriptEngine.createBindings()获得,很好理解,每次都产生一个新的。Global对应到工厂,Engine对应到ScriptEngine,向这2者里面加入任何数据或者编译后的脚本执行对象,在每一份新生成的Local Binding里面都会存在。
实例代码
/** * Bindings */ public void jsEngineBindingsTest(){ ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); Compilable compilable = (Compilable) engine; Bindings bindings = engine.createBindings(); String script = "function add(num1,num2){return num1+num2} add(a, b)"; CompiledScript JSFunction = null; try { JSFunction = compilable.compile(script); //向bingdings中传入键值对 bindings.put("a", 1); bindings.put("b", 2); //调用eval时将bindings也传入 Object result = JSFunction.eval(bindings); System.out.println(result); } catch (ScriptException e) { e.printStackTrace(); } }
此处脚本代码进行了一个简单的加法运算,结果如下:
3.0
到此这篇关于Java详解ScriptEngine接口动态执行JS脚本的文章就介绍到这了,更多相关Java ScriptEngine内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!