Nashorn 简介

news/2025/2/19 9:47:51/

1. 引言

本文重点介绍 Nashorn – 从 Java 8 开始,JVM 的新默认 JavaScript 引擎。
许多复杂的技术已被用于使 Nashorn 的性能比其前身 Rhino 高出几个数量级,因此这是一个值得的改变。让我们来看看它的一些使用方式。

本文大部分内容翻译自:https://www.baeldung.com/java-nashorn

2. 命令行

JDK 1.8 包含一个名为 jjs 的命令行解释器,它可用于运行 JavaScript 文件,或者,如果没有参数,则用作 REPL(交互式 shell):

$JAVA_HOME/bin/jjs hello.js
Hello World

这里的文件 hello.js 包含一条指令:

print("Hello world");

相同的代码可以以交互方式运行:

$JAVA_HOME/bin/jjs
jjs> print("Hello world")
Hello world

您还可以通过添加 #!$JAVA_HOME/bin/jjs 作为第一行来指示 *nix 运行时使用 jjs 来运行目标脚本:

#!$JAVA_HOME/bin/jjs
var greeting = "Hello World";
print(greeting);

然后文件可以正常运行:

$ ./hello.js
Hello World

PS: 我在macOS之中把上面的第1行替换成
#!/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/bin/jjs暂不清楚为什么$JAVA_HOME没有正确认识出来,我猜测我的$JAVA_HOME变量是用户级别的,而直接运行.js可能无法访问到我的用户的变量。

3. 嵌入式脚本引擎

在 JVM 中运行 JavaScript 的第二种可能更常见的方法是通过 ScriptEngine。JSR-223 定义了一组脚本 API,允许一个可插拔的脚本引擎架构,该架构可用于任何动态语言(当然,前提是它有一个 JVM 实现)。

让我们创建一个 JavaScript 引擎:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");Object result = engine.eval("var greeting='hello world';" +"print(greeting);" +"greeting");

在这里,我们创建一个新的 ScriptEngineManager,并立即要求它为我们提供一个名为 nashorn 的 ScriptEngine。然后,我们传递几个指令并获得结果,可以预见的是,结果是一个字符串“hello world”。

4. 将数据传递给脚本

可以通过定义 Bindings 对象并将其作为第二个参数传递给 eval 函数来将数据传递到引擎中:

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;public class 将数据传递给脚本 {public static void main(String[] args) throws Exception {ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");Bindings bindings = engine.createBindings();bindings.put("count", 3);bindings.put("name", "baeldung");String script = "var greeting='Hello ';" +"for(var i=count;i>0;i--) { " +"greeting+=name + ' '" +"}" +"greeting";Object bindingsResult = engine.eval(script, bindings);System.out.println(bindingsResult);}
}

运行此代码段会产生:“Hello baeldung baeldung baeldung”。

5. 调用 JavaScript 函数

当然,可以从 Java 代码中调用 JavaScript 函数:

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;public class 调用Javascript函数 {public static void main(String[] args) throws Exception {ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");engine.eval("function composeGreeting(name) {" +"return 'Hello ' + name" +"}");Invocable invocable = (Invocable) engine;Object funcResult = invocable.invokeFunction("composeGreeting", "baeldung");System.out.println(funcResult);}
}

这将返回“Hello baeldung”。

6. 使用 Java 对象

由于我们在 JVM 中运行,因此可以在 JavaScript 代码中使用本机 Java 对象。

这是通过使用 Java 对象实现的:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;public class 使用Java对象 {public static void main(String[] args) throws Exception {ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");Object map = engine.eval("var HashMap = Java.type('java.util.HashMap');" +"var map = new HashMap();" +"map.put('hello', 'world');" +"map");System.out.println(map);}
}

7. 语言扩展

Nashorn 的目标是 ECMAScript 5.1,但它确实提供了扩展,使 JavaScript 的使用变得更好一些。

获取javascript中的变量的值

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleScriptContext;public class NashornTest {public static void main(String[] args) throws Exception {final ScriptEngineManager factory = new ScriptEngineManager();final ScriptEngine engine = factory.getEngineByName("nashorn");final String raw = "I am the raw value injected";final ScriptContext ctx = new SimpleScriptContext();// **This is the inserted line**ctx.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);String script = "var result = 'I am a result';";script += "java.lang.System.out.println(raw);";script += "'I am a returned value';";final Object res = engine.eval(script, ctx);System.out.println(ctx.getAttribute("result"));System.out.println(res);}
}

摘自:
https://stackoverflow.com/questions/42338239/access-variable-of-scriptcontext-using-nashorn-javascript-engine-java-8

参考

https://www.baeldung.com/java-nashorn


http://www.ppmy.cn/news/1259696.html

相关文章

SAP CA01/CA02 创建及更新工艺路线BAPI

前言 最近需要做一个routing的批导,初步查过资料后,发现下面几个BAPI: BAPI_ROUTING_CREATE:最常用的BAPI,只支持创建,没有对应的CHANGE BAPI; ROUTING_MAINTAIN:不支持创建,只支…

flink源码分析之功能组件(四)-slot管理组件I

简介 本系列是flink源码分析的第二个系列,上一个《flink源码分析之集群与资源》分析集群与资源,本系列分析功能组件,kubeclient,rpc,心跳,高可用,slotpool,rest,metrics&…

书-用数组存储高于60低于70的人单独存起来

#include<stdio.h> # define N 10 //书-用数组存储高于60低于70的人单独存起来 int main(){float s[N]{68.2,62.3,63.4,34.5,45.6,56.7,67.8,78.9,89.0,100};int i;float diyu[100];int j0;for(i0;i<N;i){if(s[i]>60 && s[i]<70)diyu[j]s[i];//这里的范…

【408】计算机学科专业基础 - 计算机组成原理

一、计算机系统概述 【复习提示】 本章是组成原理的概述&#xff0c;考查时易针对有关概念或性能指标出选择题&#xff0c;也可能综合后续章节的内容出有关性能分析的综合题。掌握本章的基本概念&#xff0c;是学好后续章节的基础。部分知识点在初学时理解不深刻也无须担忧&am…

2023亚太地区五岳杯量子计算挑战赛

计算电源网 (CPN&#xff09;布局优化 1. 介绍 计算能力网络 &#xff08;CPN&#xff09;是一种基于业务需求分配和调度计算资源的新型信息基础设施&#xff0c;计算资源通常由终端用户、边缘服务器和云服务器组成。该网络旨在满足各种计算任务的需求。根据计算需求的空间分…

01、pytest:帮助你编写更好的程序

简介 ​pytest框架可以很容易地编写小型、可读的测试&#xff0c;并且可以扩展以支持应用程序和库的复杂功能测试。使用pytest至少需要安装Python3.7或PyPy3。PyPI包名称为pytest 一个快速的例子 # content of test_sample.py def inc(x):return x1def test_ansewer():asser…

PCI/PCIe转打印口/并口Linux系统使用说明

PCIe转打印口芯片CH382/CH384以及PCI转打印口芯片CH351/CH352/CH353/CH356CH358 打印口转接方案支持Windows和Linux操作系统&#xff0c;在系统下会生成独立的打印口&#xff0c;本文主要介绍Linux操作系统如何为设备加载打印口驱动。 确认系统是否默认支持 Linux系统是自带并…

基于深度学习的表情动作单元识别综述

论文标题&#xff1a;基于深度学习的表情动作单元识别综述 作者&#xff1a;邵志文1&#xff0c;2&#xff0c;周 勇1&#xff0c;2&#xff0c;谭 鑫3&#xff0c;马利庄3&#xff0c;4&#xff0c;刘 兵1&#xff0c;2&#xff0c;姚 睿1&#xff0c;2 发表日期&#xff1a…