Java 脚本引擎的使用

本文介绍了Java如何使用Nashorn引擎与JavaScript进行交互,包括通过ScriptEngineManager获取脚本引擎,按扩展名、MIME类型或名称获取引擎,以及参数传递、脚本编译和动态调用脚本方法的功能。Nashorn提供了在Java中执行JavaScript代码的能力,增强了系统的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 前言

Java 6 版本就已经引入了 Rhino 引擎用以支持脚本代码运行,而从 Java 8 开始 Nashorn 取代 Rhino 成为 Java 内嵌的 JavaScript 引擎。Nashorn 引擎允许开发人员将 JavaScript 代码嵌入到 Java 中执行,这个特性在复杂的配置系统中有比较大的应用价值,可以满足特定场景下的灵活性要求

以下示例代码可以列出所有脚本引擎工厂的相关属性,可以看到其支持的脚本引擎包括了 JavaScript 等

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        manager.getEngineFactories().forEach(factory -> System.out.printf("Name: %s%n" +
                        "Version: %s%n" +
                        "Language name: %s%n" +
                        "Language version: %s%n" +
                        "Extensions: %s%n" +
                        "Mime types: %s%n" +
                        "Names: %s%n",
                factory.getEngineName(),
                factory.getEngineVersion(),
                factory.getLanguageName(),
                factory.getLanguageVersion(),
                factory.getExtensions(),
                factory.getMimeTypes(),
                factory.getNames()));
    }

在这里插入图片描述

2. 脚本引擎的使用

Java 脚本引擎 API 中最主要的是 ScriptEngineManager,开发者可以通过这个类获取当前 Java 版本所支持的所有脚本引擎,具体获取脚本引擎的方法有以下3种:

  1. 根据扩展名得到脚本引擎
     ScriptEngineManager manager = new ScriptEngineManager();
     // getEngineByExtension 的参数就是 Extensions:[js]中任一个
     ScriptEngine engine = manager.getEngineByExtension("js");
    
  2. 根据Mime类型得到脚本引擎
    ScriptEngineManager manager = new ScriptEngineManager();
    // getEngineByMimeType 的参数可以是 Mime types: [application/javascript, application/ecmascript, text/javascript, text/ecmascript]中的任一个
    ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
    
  3. 根据名称得到脚本引擎
    ScriptEngineManager manager = new ScriptEngineManager();
    // getEngineByName 的参数可以是 Names: [js, rhino, JavaScript, javascript, ECMAScript, ecmascript] 
    // 中的任一个
    ScriptEngine engine = manager.getEngineByName("javascript");
    

2.1 脚本参数传递

脚本引擎除了简单的执行功能,还可以通过它向脚本中传递参数,同时也可以将脚本中的变量值取出来。这些功能要依靠 ScriptEngine#put()ScriptEngine#get() 方法,以下为代码示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        // 获取javascript脚本引擎
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 参数出入
            engine.put("name", "lucky");
            // 开始执行脚本
            engine.eval("var output ='' ;" +
                    "for (i = 0; i <= name.length; i++) {" +
                    "    output = name.charAt(i) + output" +
                    "}");
            // 得到output变量的值
            String name = (String) engine.get("output");
            System.out.printf("被翻转后的字符串:%s", name);
        } catch (Exception e) {
            System.err.println(e);
        }
    }

2.2 脚本编译

如我们所知,脚本解释执行的运行方式性能很低,但是不少脚本语言都支持编译功能,因此 Java 的脚本引擎也对编译进行了支持。如果某段脚本要运行多次的话,可以使用编译的方式将其转化为执行效率更高的形式,从而提高性能

具体做法是调用 ScriptEngine#compile() 方法进行脚本编译,不过只有实现了Compilable 接口的脚本引擎才可以进行编译,可参考以下示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        // 得到javascript脚本引擎
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 可编译的脚本,提高执行速度
            engine.put("counter", 0);
            // 判断这个脚本引擎是否支持编译功能
            if (engine instanceof Compilable) {
                Compilable compEngine = (Compilable) engine;
                CompiledScript script = compEngine.compile("function count() { " +
                        "    counter = counter +1; " +
                        "    return counter; " +
                        "};" +
                        "count();");
                System.out.printf("Counter: %s%n", script.eval());
                System.out.printf("Counter: %s%n", script.eval());
                System.out.printf("Counter: %s%n", script.eval());
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }

在这里插入图片描述

2.3 脚本动态调用

业务系统运行时通常需要将用户的输入作为入参执行函数,这就产生了脚本方法动态调用的需求。和编译一样,脚本引擎必须实现 Invocable 接口才可以动态调用脚本中的方法,具体可参考以下示例

    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            // 动态决定脚本调用
            String name = "nathan";
            if (engine instanceof Invocable) {
                engine.eval("function reverse(name) {" +
                        " var output =' ';" +
                        " for (i = 0; i <= name.length; i++) {" +
                        "     output = name.charAt(i) + output" +
                        " }" +
                        " return output;" +
                        "}");
                Invocable invokeEngine = (Invocable) engine;
                Object o = invokeEngine.invokeFunction("reverse", name);
                System.out.printf("翻转后的字符串:%s", o);
            }
        } catch (Exception e) {
            System.err.println(e);
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值