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);
    }
}

执行结果

javadoc gradle脚本_javadoc gradle脚本

如果你不确定系统中哪些脚本引擎是可用的,可以通过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());
        }
    }
}

执行结果

javadoc gradle脚本_java_02

常用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);
    }
}

执行结果

javadoc gradle脚本_Java_03