JAVA脚本引擎
什么是JAVA脚本引擎
Java 平台自带了如JavaScript、Groovy等脚本语言的引擎,可以在运行时动态地加载和执行脚本代码。这些脚本引擎可以直接在Java应用程序中使用,例如,通过ScriptEngineManager来获取特定脚本语言的ScriptEngine实例,然后使用eval()方法执行脚本代码。
Java 脚本引擎使得Java 应用程序可以通过一套固定的接口与各种脚本引擎交互,从而达到在Java平台上调用各种脚本语言的目的。Java 脚本API是连通Java平台和脚本语言的桥梁,可以把一些复杂异变的业务逻辑交给脚本语言处理,这大大提高了开发效率。
自JDK1.6开始,Java引入了脚本引擎的功能,并基于Rhino引擎实现。而在JDK1.8之后,Java开始使用Nashorn引擎,它支持ECMAScript 5标准,在JDK 11及以后是GraalVM的JavaScript实现。需要注意的是,这些技术细节可能会随着Java版本的更新而发生变化。
除此之外,还有像JRuby和Jython这样的工具,它们分别是Ruby和Python语言的Java实现,允许在Java应用程序中运行对应的脚本语言,实现与Java的无缝集成和互操作性。
脚本引擎对象获取
创建ScriptEngineManager实例
package demo1;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
/**
* Java 脚本引擎及简单使用
*
* @author Anna.
* @date 2024/4/4 15:37
*/
public class ScriptEngineDemo {
public static void main(String[] args) throws Exception {
// 创建ScriptEngineManager实例
ScriptEngineManager manager = new ScriptEngineManager();
// 通过ScriptEngineManager获取特定的脚本引擎。调用getEngineByName传入需要使用的脚本引擎名称(比如JavaScript)即可
ScriptEngine engineByName = manager.getEngineByName("JavaScript");
// 使用ScriptEngine执行脚本。一旦你有了ScriptEngine的实例,你可以使用eval方法来执行脚本
Object evalRtn = engineByName.eval("'1' + 20");
System.out.println(evalRtn);
}
}
执行结果
如果你不确定系统中哪些脚本引擎是可用的,可以通过ScriptEngineManager的getEngineFactories方法来获取所有可用的脚本引擎工厂,进而了解可用的脚本引擎类型。
package demo1;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
/**
* 查看系统中可用的所有脚本引擎的信息
*
* @author Anna.
* @date 2024/4/4 15:37
*/
public class ScriptEngineDemo2 {
public static void main(String[] args) throws Exception {
// 创建ScriptEngineManager实例
ScriptEngineManager manager = new ScriptEngineManager();
// 获取所有可用的脚本引擎工厂
for (ScriptEngineFactory factory : manager.getEngineFactories()) {
System.out.println("ScriptEngineFactory Info:");
System.out.println(" Script Engine Name: " + factory.getEngineName());
System.out.println(" Script Engine Version: " + factory.getEngineVersion());
System.out.println(" Script Engine Language: " + factory.getLanguageName());
System.out.println(" Script Engine Language Version: " + factory.getLanguageVersion());
System.out.println(" Names: " + factory.getNames());
System.out.println(" Mime Types: " + factory.getMimeTypes());
System.out.println(" Extensions: " + factory.getExtensions());
}
}
}
执行结果
常用API
Java 脚本引擎提供了丰富的API,使得开发者能够灵活地执行和管理脚本。
JDK1.6开始,Java引入了脚本引擎的功能,并基于Rhino引擎实现。而在JDK1.8之后,Java开始使用Nashorn引擎,它支持ECMAScript 5标准,在JDK 11及以后是GraalVM的JavaScript实现。
不同版本相应方法可能有所差异,因此建议查阅相应文档以获取最准确的信息和示例代码
以下是Java8脚本引擎中一些常用的API及其描述:
类型 | 方法 | 描述 |
ScriptEngineManager | - | ScriptEngineManager类用于管理脚本引擎。它是获取脚本引擎实例的工厂类。 |
- | getEngineByName(String name) | 根据指定的脚本语言名称获取脚本引擎。 |
- | getEngineFactories() | 获取所有可用的脚本引擎工厂。 |
ScriptEngineScriptEngine | - | 接口定义了执行脚本的基本方法。 |
- | eval(String script) | 执行传入的脚本字符串,并返回脚本的结果。 |
- | put(String key, Object value) | 将Java对象绑定到脚本引擎的上下文中,以便在脚本中使用。 |
- | get(String key) | 从脚本引擎的上下文中获取绑定的Java对象。 |
Invocable | - | 如果脚本引擎支持Java反射API,那么它的ScriptEngine实例也会实现Invocable接口。 |
- | invokeFunction(String name, Object… args) | 调用脚本中定义的函数。 |
- | getMethod(String name, Class<?>… parameterTypes) | 获取脚本中定义的函数或方法的Method对象。 |
BindingsBindings | - | 接口表示存储键值对的集合,用于在脚本和Java之间共享数据。 |
- | put(String name, Object value) | 将键值对添加到绑定中。 |
- | get(Object key) | 从绑定中获取与键关联的值。 |
ScriptContext | - | ScriptContext接口表示脚本引擎的上下文,用于管理脚本引擎的输入、输出和错误流,以及引擎的绑定。 |
- | getEngineScope() | 获取与脚本引擎相关的绑定。 |
- | setWriter(Writer writer) | 设置脚本引擎的输出流。 |
- | setErrorWriter(Writer writer) | 设置脚本引擎的错误流。 |
测试案例
package demo2;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.List;
import java.util.function.Consumer;
/**
* 脚本引擎使用测试案例
*
* @author Anna.
* @date 2024/4/4 15:53
*/
public class ScriptEngineDemo {
public static void main(String[] args) throws Exception {
// 创建脚本引擎管理对象
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
// 获取js脚本引擎对象
ScriptEngine jsEngine = scriptEngineManager.getEngineByName("js");
// 通过Jjava方法定义变量,存储到引擎上下文中
jsEngine.put("name", "张三");
// 通过执行脚本定义
jsEngine.eval("var age = 30;");
// 输出上下文中变量的值
System.out.printf("输出两种方式定义变量,引擎上限文中的值:name=%s,age=%s%n", jsEngine.get("name"), jsEngine.get("age"));
// 通过脚本定义函数
jsEngine.eval("function add(a,b){return a + b;}");
// 执行函数
Invocable jsInvocable = (Invocable) jsEngine;
Object addRtn = jsInvocable.invokeFunction("add", 30, 20);
System.out.printf("输出调用脚本定义函数结果值:%s%n", addRtn);
// 脚本引擎中导入java包
String jsCode = "var list = Java.type('java.util.Arrays').asList(\"张三\",\"李四\");";
jsEngine.eval(jsCode);
// 获取js中通过java类中方法定义的变量,并输出
List<String> list = (List<String>) jsEngine.get("list");
for (String item : list) {
System.out.println(item);
}
}
/**
* 定义打印的方法
*
* @param str
* @param consumer
* @return void
* @author Anna.
* @date 2024/4/4 16:38
*/
public static void print(String str, Consumer<String> consumer) {
consumer.accept(str);
}
}
执行结果