Java脚本引擎入门

编程

Java Script Engine

Java 脚本引擎可以将脚本嵌入Java代码中,可以自定义和扩展Java应用程序,自JDK1.6被引入,基于Rhino引擎,JDK1.8后使用Nashorn引擎,支持ECMAScript 5,但后期还可能会换。

脚本引擎包位于javax.script中,各个类名及描述如下

接口

  • Bindings

    键值对映射,所有key都为String

  • Compilable

    由具体的脚本引擎实现,用于将脚本进行编译,可重复使用。

  • Invocable 由具体的脚本引擎实现,其允许调用先前已执行的脚本

  • ScriptContext

    脚本引擎上下文,用于将应用程序与脚本引擎进行绑定

  • ScriptEngine

    由具体的脚本引擎实现,定义了执行脚本的方法、键值对映射关系、脚本引擎上下文

  • ScriptEngineFactory

    脚本引擎工厂,每一个ScriptEngine都有一个对应的工厂。ScriptEngineManager会从ClassLoader中获取所有的ScriptEngineFactories实例

  • AbstractScriptEngine

    ScriptEngine的抽象实现类,提供了ScriptEngine的标准实现

  • CompiledScript

    由存储编译结果的类扩展。可以以Java类、Java类文件或者脚本操作码的形式存储,可以重复执行无需重新解析。每个CompiledScript都与一个ScriptEngine相关联,调用CompiledScript的eval方法会导致ScriptEngine执行

  • ScriptEngineManager

    脚本引擎管理器,提供ScriptEngine的实例化机制,并维护了一些键/值对集合,供所有创建的ScriptEngine共享使用

  • SimpleBindings

    使用HashMap 或者其他Map实现的一种简单键值映射

  • SimpleScriptContext

    ScriptContext 的一种简单实现

异常

  • ScriptException

    脚本API的通用异常类,抛出的异常类具有文件名、行号、列号信息

示例

简单的

@Test

public void scriptTest() throws ScriptException {

ScriptEngineManager engineManager = new ScriptEngineManager();

//获取JavaScript解析引擎

ScriptEngine engine = engineManager.getEngineByName("JavaScript");

//将x变量映射为Hello World!

engine.put("x", "Hello World!");

engine.eval("print(x)");

}

//输出

//Hello World!

较复杂的

从文件中读取脚本

/**

* 从文件中读取Js脚本

* test.js 中的内容:

* var obj = new Object();

* obj.hello = function (name) {

* print("Hello, " + name);

* }

* @throws Exception

*/

@Test

public void file() throws Exception{

ScriptEngineManager manager = new ScriptEngineManager();

ScriptEngine engine = manager.getEngineByName("JavaScript");

engine.eval(new FileReader(new File("script/test.js")));

Invocable inv = (Invocable) engine;

Object obj = engine.get("obj");

inv.invokeMethod(obj, "hello", "Script Test!" );

}

将Java变量注入脚本中

有可能需要在脚本中使用Java变量

@Test

public void scriptVar() throws Exception{

ScriptEngineManager manager = new ScriptEngineManager();

ScriptEngine engine = manager.getEngineByName("JavaScript");

File file = new File("F:/test/test.txt");

//将File对象f直接注入到js脚本中并可以作为全局变量使用

engine.put("files", file);

engine.eval("print(files.getPath());print(files.getName());");

}

调用脚本中的方法

使用Invocable 调用已经加载脚本中的方法

@Test

public void scriptTest1() throws ScriptException, NoSuchMethodException {

ScriptEngineManager engineManager = new ScriptEngineManager();

ScriptEngine engine = engineManager.getEngineByName("JavaScript");

StringBuilder sb = new StringBuilder();

sb.append("var obj = new Object();");

sb.append("obj.hello = function(name){print("Hello, " + name);}");

engine.eval(sb.toString());

//Invocable 可以调用已经加载过的脚本

Invocable invocable = (Invocable) engine;

//获取脚本的obj对象

Object object = engine.get("obj");

//调用obj对象的hello函数

invocable.invokeMethod(object, "hello", "Script Method!");

}

//输出

//Hello, Script Method!

多个作用域

一个脚本引擎,多个scope,x变量并没有覆盖之前的变量

@Test

public void scriptTest() throws ScriptException {

ScriptEngineManager engineManager = new ScriptEngineManager();

ScriptEngine engine = engineManager.getEngineByName("JavaScript");

engine.put("x", "Hello World!");

engine.eval("print(x)");

ScriptContext context = new SimpleScriptContext();

//新的Script context绑定ScriptContext的ENGINE_SCOPE

Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);

// 增加一个新变量到新的范围 engineScope 中

bindings.put("x", "word hello!!");

// 执行同一个脚本 - 但这次传入一个不同的script context

engine.eval("print(x);", bindings);

engine.eval("print(x);");

}

//输出

//Hello World!

//word hello!!

//Hello World!

使用脚本实现Java接口

@Test

public void runnableImpl() throws Exception{

ScriptEngineManager manager = new ScriptEngineManager();

ScriptEngine engine = manager.getEngineByName("JavaScript");

// String里定义一段JavaScript代码脚本

String script = "function run() { print("run called"); }";

// 执行这个脚本

engine.eval(script);

// 从脚本引擎中获取Runnable接口对象(实例). 该接口方法由具有相匹配名称的脚本函数实现。

Invocable inv = (Invocable) engine;

// 在上面的脚本中,我们已经实现了Runnable接口的run()方法

Runnable runnable = inv.getInterface(Runnable.class);

// 启动一个线程运行上面的实现了runnable接口的script脚本

Thread thread = new Thread(runnable);

thread.start();

Thread.sleep(1000);

}

如果脚本是基于对象的,则可以通过执行脚本的方法来实现Java接口,避免调用脚本的全局函数。

@Test

public void runnableObject() throws ScriptException {

ScriptEngineManager manager = new ScriptEngineManager();

ScriptEngine engine = manager.getEngineByName("JavaScript");

String script = "var obj = new Object();obj.run = function() {println("run method called")}";

engine.eval(script);

//获得脚本对象

Object object = engine.get("obj");

Invocable invocable = (Invocable) engine;

Runnable runnable = invocable.getInterface(object, Runnable.class);

Thread thread = new Thread(runnable);

thread.start();

Thread.sleep(1000);

}

以上是 Java脚本引擎入门 的全部内容, 来源链接: utcz.com/z/511614.html

回到顶部