27、Java与Nashorn脚本交互:API使用与调试技巧

Java与Nashorn脚本交互:API使用与调试技巧

1. Java与Nashorn交互的基础API

在Java中与Nashorn脚本交互时, ScriptObjectMirror 类是一个关键类,它实现了 JSObject Bindings 接口,提供了多种操作脚本对象属性的方法。以下是一些常用方法的介绍:
| 方法 | 描述 |
| — | — |
| void removeMember(String name) | 从对象中移除指定属性 |
| void setMember(String name, Object value) | 设置对象指定属性的值,若属性不存在则添加新属性 |
| void setSlot(int index, Object value) | 设置对象指定索引属性的值,若索引不存在则添加新属性 |
| double toNumber() | 返回对象的数值,若对象不是数值包装则返回 Double.NAN |
| Collection<Object> values() | 返回对象所有属性值的集合 |

这些方法让我们可以方便地操作脚本对象的属性。例如,使用 setMember 方法可以添加或更新属性,使用 removeMember 方法可以删除属性。

同时,我们可以通过 JSObject Bindings 接口的不同方法来访问脚本对象的属性:
- getMember() getSlot() 方法用于读取命名和索引属性。
- get() 方法用于获取属性值。
- hasMember() hasSlot() 方法用于检查命名和索引属性是否存在。
- containsKey() 方法用于检查属性是否存在。

可以将 JSObject Bindings 接口看作是对同一脚本对象的不同视角,前者将脚本对象视为简单的Java类,后者将其视为一个映射。

下面是一个示例,展示了如何在Java中操作脚本对象的属性:

// scriptobjectprop.js
// Create an object
var point = {x: 10, y: 20};
// Create an array
var empIds = [101, 102];
// Get the Java type
var ScriptObjectProperties = Java.type("com.jdojo.script.ScriptObjectProp");
// Pass the object to Java
ScriptObjectProperties.propTest(point);
// Print all properties of the point object
print("In script, after calling the Java method propTest()...");
for(var prop in point) {
    var value = point[prop];
    print(prop + " = " + value);
}
// Pass the array object to Java
ScriptObjectProperties.arrayTest(empIds);
// Print all elements of the empIds array
print("In script, after calling the Java method arrayTest()...");
for(var i = 0, len = empIds.length; i < len; i++) {
    var value = empIds[i];
    print("empIds[" + i + "] = " + value);
}
// ScriptObjectProp.java
package com.jdojo.script;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class ScriptObjectProp {
    public static void main(String[] args) {
        // Construct the script file path
        String scriptFileName = "scriptobjectprop.js";
        Path scriptPath = Paths.get(scriptFileName);
        // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
        if (!Files.exists(scriptPath)) {
            System.out.println(scriptPath.toAbsolutePath() + " does not exist.");
            return;
        }
        // Create a scripting engine manager
        ScriptEngineManager manager = new ScriptEngineManager();
        // Obtain a Nashorn scripting engine from the manager
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            // Execute the script that will call the propTest() and arrayTest() methods of this class
            engine.eval("load('" + scriptFileName + "')");
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
    public static void propTest(ScriptObjectMirror point) {
        // List all properties
        System.out.println("Properties of point received in Java...");
        for (String prop : point.keySet()) {
            Object value = point.getMember(prop);
            System.out.println(prop + " = " + value);
        }
        // Let us add a property named z
        System.out.println("Adding z = 30 to point in Java... ");
        point.setMember("z", 30);
    }
    public static void arrayTest(ScriptObjectMirror empIds) {
        if (!empIds.isArray()) {
            System.out.println("Passed in object is not an array.");
            return;
        }
        // Get the length property of the array
        int length = ((Number) empIds.getMember("length")).intValue();
        System.out.println("empIds received in Java...");
        for (int i = 0; i < length; i++) {
            int value = ((Number) empIds.getSlot(i)).intValue();
            System.out.printf("empIds[%d] = %d%n", i, value);
        }
        // Let us add an element to the array
        System.out.println("Adding empIds[2] = 103 in Java... ");
        empIds.setSlot(length, 103);
    }
}

这个示例中,脚本创建了一个对象 point 和一个数组 empIds ,并将它们传递给Java方法。Java方法打印对象属性并添加新属性,脚本在方法返回后再次打印属性以确认新属性已添加。

2. 在Java中创建Nashorn对象

有时候我们需要在Java中使用脚本中的构造函数来创建对象。 ScriptObjectMirror 类的 newObject() 方法可以帮助我们实现这一功能,其方法声明如下:

Object newObject(Object... args)

该方法的参数是传递给构造函数的参数,返回新对象的引用。使用该方法前,需要先获取构造函数的引用,然后调用该方法创建新的脚本对象。

下面是一个示例,展示了如何在Java中创建 Point 对象并调用其方法:

// Point.js
// Define the Point constructor
function Point(x, y) {
    this.x = x;
    this.y = y;
}
// Override the toString() method in Object.prototype
Point.prototype.toString = function() {
    return "Point(" + this.x + ", " + this.y + ")";
};
// Define a new method called distance()
Point.prototype.distance = function(otherPoint) {
    var dx = this.x - otherPoint.x;
    var dy = this.y - otherPoint.y;
    var dist = Math.sqrt(dx * dx + dy * dy);
    return dist;
};
// CreateScriptObject.java
package com.jdojo.script;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class CreateScriptObject {
    public static void main(String[] args) {
        // Construct the script file path
        String scriptFileName = "point.js";
        Path scriptPath = Paths.get(scriptFileName);
        // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
        if (! Files.exists(scriptPath) ) {
            System.out.println(scriptPath.toAbsolutePath() + " does not exist.");
            return;
        }
        // Get the Nashorn script engine
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            // Execute the script in the file
            engine.eval("load('" + scriptFileName + "');");
            // Get the Point constructor as a ScriptObjectMirror object
            ScriptObjectMirror pointFunc = (ScriptObjectMirror)engine.get("Point");
            // Create two Point objects. The following statements are the same as var p1 = new Point(10, 20); and var p2 = new Point(13, 24); in a Nashorn script
            ScriptObjectMirror p1 = (ScriptObjectMirror)pointFunc.newObject(10, 20);
            ScriptObjectMirror p2 = (ScriptObjectMirror)pointFunc.newObject(13, 24);
            // Compute the distance between p1 and p2 calling the distance() method of the Point object
            Object result = p1.callMember("distance", p2);
            double dist = ((Number)result).doubleValue();
            // Get the string forms of p1 and p2 by calling their toString() method
            String p1Str = (String)p1.callMember("toString");
            String p2Str = (String)p2.callMember("toString");
            System.out.printf("The distance between %s and %s is %.2f.%n", p1Str, p2Str, dist);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这个示例中,Java程序加载 Point.js 脚本,获取 Point 构造函数的引用,创建两个 Point 对象,计算它们之间的距离并打印结果。

3. 从Java调用脚本函数

我们还可以在Java代码中调用脚本函数。通过 ScriptObjectMirror call() 方法可以实现这一功能,其方法声明如下:

Object call(Object thiz, Object... args)

第一个参数是函数调用时的 this 值,第二个参数是传递给函数的参数列表。若要在全局作用域调用函数,第一个参数使用 null

下面是一个调用 factorial 函数的示例:

// factorial.js
// Returns true if n is an integer. Otherwise, returns false.
function isInteger(n) {
    return typeof n === "number" && isFinite(n) && n%1 === 0;
}
// Define a function that computes and returns the factorial of an integer
function factorial(n) {
    if (!isInteger(n)) {
        throw new TypeError("The number must be an integer. Found:" + n);
    }
    if(n < 0) {
        throw new RangeError("The number must be greater than 0. Found: " + n);
    }
    var fact = 1;
    for(var counter = n; counter > 1; fact *= counter--);
    return fact;
}
// InvokeScriptFunctionInJava.java
package com.jdojo.script;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class InvokeScriptFunctionInJava {
    public static void main(String[] args) {
        // Construct the script file path
        String scriptFileName = "factorial.js";
        Path scriptPath = Paths.get(scriptFileName);
        // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
        if (!Files.exists(scriptPath)) {
            System.out.println(scriptPath.toAbsolutePath() + " does not exist.");
            return;
        }
        // Get the Nashorn script engine
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            // Execute the script in the file, so the factorial() function is loaded
            engine.eval("load('" + scriptFileName + "');");
            // Get the reference of the factorial() script function
            ScriptObjectMirror factorialFunc = (ScriptObjectMirror)engine.get("factorial");
            // Invoke the factorial function and print the result
            Object result = factorialFunc.call(null, 5);
            double factorial = ((Number) result).doubleValue();
            System.out.println("Factorial of 5 is " + factorial);
            /* Call the Array.prototype.join() function on a String object */
            // Get the reference of the Array.prototype.join method
            ScriptObjectMirror arrayObject = (ScriptObjectMirror)engine.eval("Array.prototype");
            ScriptObjectMirror joinFunc = (ScriptObjectMirror)arrayObject.getMember("join");
            // Call the join() function of Array.prototype on a string object passing a hyphen as a separator
            String thisObject = "Hello";
            String separator = "-";
            String joinResult = (String)joinFunc.call(thisObject, separator);
            System.out.println(joinResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这个示例中,Java程序加载 factorial.js 脚本,获取 factorial 函数的引用,调用该函数计算5的阶乘并打印结果,同时还调用了 Array.prototype.join() 函数对字符串进行处理。

4. 脚本日期转换为Java日期

将脚本中的日期对象转换为Java日期对象不是一件直接的事情。不过,由于JavaScript日期和Java日期都基于同一纪元(1970年1月1日午夜UTC),我们可以通过获取JavaScript日期自纪元以来的毫秒数,创建 Instant 对象,再从 Instant 创建 ZonedDateTime 对象。

以下是一个完整的示例:

// ScriptDateToJavaDate.java
package com.jdojo.script;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class ScriptDateToJavaDate {
    public static void main(String[] args) {
        // Get the Nashorn script engine
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            // Create a Date object in script
            ScriptObjectMirror jsDt = (ScriptObjectMirror)engine.eval("new Date()");
            // Get the string representation of the script date
            String jsDtString = (String) jsDt.callMember("toString");
            System.out.println("JavaScript Date: " + jsDtString);
            // Get the epoch milliseconds from the script date
            long jsMillis = ((Number) jsDt.callMember("getTime")).longValue();
            // Convert the milliseconds from JavaScript date to java Instant
            Instant instant = Instant.ofEpochMilli(jsMillis);
            // Get a ZonedDateTime for the system default zone id
            ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
            System.out.println("Java ZonedDateTime: " + zdt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这个示例中,Java程序创建了一个脚本日期对象,获取其字符串表示和自纪元以来的毫秒数,将毫秒数转换为 Instant 对象,再创建 ZonedDateTime 对象并打印结果。

5. 调试、追踪和性能分析脚本

NetBeans 8及以上版本结合JDK 8或更高版本支持对Nashorn脚本进行调试、追踪和性能分析。以下是相关的操作内容:
- 调试独立的Nashorn脚本 :可以在NetBeans IDE中运行和调试独立的Nashorn脚本,使用与调试Java代码相同的调试功能,如设置断点、显示变量值、添加监视、监控调用栈等。
- 调试从Java代码调用的Nashorn脚本 :同样可以在NetBeans IDE中调试从Java代码调用的Nashorn脚本,调试器会显示Nashorn栈。
- 追踪和性能分析Nashorn脚本 :NetBeans提供了追踪和性能分析Nashorn脚本的功能,帮助我们了解脚本的执行情况。

以下是一个用于调试的示例脚本:

// primetest.js
function isPrime(n) {
    // Integers <= 2, floating-point numbers, and even numbers are not primes
    if (n <= 2 || Math.floor(n) !== n || n % 2 === 0) {
        return false;
    }
}

在NetBeans中,我们可以使用菜单 Windows ➤ Debugging 打开所有与调试器相关的面板。若要查看完整的调试功能列表,可以在NetBeans应用程序处于活动状态时按F1键打开帮助页面。

综上所述,通过Java APIs for Nashorn,我们可以在Java代码中方便地与Nashorn脚本进行交互,包括操作脚本对象属性、创建脚本对象、调用脚本函数以及进行日期转换等。同时,利用NetBeans IDE的调试、追踪和性能分析功能,可以更好地开发和优化Nashorn脚本。

Java与Nashorn脚本交互:API使用与调试技巧

6. 总结Java与Nashorn脚本交互要点

Java提供了丰富的API用于与Nashorn脚本进行交互,所有相关的类都在 jdk.nashorn.api.scripting 包中。下面通过一个表格来总结不同脚本类型值在Java中的对应表示:
| 脚本类型 | Java表示 |
| — | — |
| Number | java.lang.Number |
| Boolean | java.lang.Boolean |
| Null | null |
| String | java.lang.String |
| 脚本对象 | ScriptObjectMirror类的对象 |

NashornScriptEngineFactory ScriptEngine 类分别代表Nashorn脚本引擎工厂和脚本引擎。若要向Nashorn引擎传递选项,可以直接使用这些类,也可以在命令行使用 -Dnashorn.args="<options>" 。例如,传递 --globals-per-engine 选项,所有脚本上下文将共享全局变量,默认情况下脚本上下文不共享全局变量。

ScriptObjectMirror 类是操作脚本对象的核心类,它实现了 JSObject Bindings 接口,提供了丰富的方法来处理脚本对象的属性和方法,以下是一些常用操作的总结:
- 获取属性值 :使用 getMember() getSlot() get() 方法。
- 添加或更新属性值 :使用 setMember() setSlot() put() 方法。
- 调用脚本对象的方法 :使用 callMember() 方法。
- 调用脚本函数 :使用 call() 方法,可以传递 this 值。

此外, ScriptObjectMirror 类还有其他实用方法,如 seal() freeze() preventExtensions() 用于密封、冻结和防止脚本对象扩展, to() 方法用于将脚本对象转换为指定类型。

7. 操作步骤与流程图

下面为大家详细介绍在Java中与Nashorn脚本交互的操作步骤:
1. 创建脚本引擎 :使用 ScriptEngineManager 获取Nashorn脚本引擎。
2. 执行脚本 :通过 engine.eval() 方法执行脚本文件。
3. 获取脚本对象或函数引用 :使用 engine.get() 方法获取脚本对象或函数的引用。
4. 操作脚本对象或调用函数 :根据需求使用 ScriptObjectMirror 类的方法进行操作。

下面是对应的mermaid流程图:

graph LR
    A[创建脚本引擎] --> B[执行脚本]
    B --> C[获取脚本对象或函数引用]
    C --> D[操作脚本对象或调用函数]
8. 代码示例总结

为了方便大家回顾和使用,下面将前面的代码示例进行分类总结:
- 操作脚本对象属性
- 脚本文件 scriptobjectprop.js
javascript // scriptobjectprop.js // Create an object var point = {x: 10, y: 20}; // Create an array var empIds = [101, 102]; // Get the Java type var ScriptObjectProperties = Java.type("com.jdojo.script.ScriptObjectProp"); // Pass the object to Java ScriptObjectProperties.propTest(point); // Print all properties of the point object print("In script, after calling the Java method propTest()..."); for(var prop in point) { var value = point[prop]; print(prop + " = " + value); } // Pass the array object to Java ScriptObjectProperties.arrayTest(empIds); // Print all elements of the empIds array print("In script, after calling the Java method arrayTest()..."); for(var i = 0, len = empIds.length; i < len; i++) { var value = empIds[i]; print("empIds[" + i + "] = " + value); }
- Java文件 ScriptObjectProp.java
```java
// ScriptObjectProp.java
package com.jdojo.script;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import jdk.nashorn.api.scripting.ScriptObjectMirror;

public class ScriptObjectProp {
    public static void main(String[] args) {
        // Construct the script file path
        String scriptFileName = "scriptobjectprop.js";
        Path scriptPath = Paths.get(scriptFileName);
        // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
        if (!Files.exists(scriptPath)) {
            System.out.println(scriptPath.toAbsolutePath() + " does not exist.");
            return;
        }
        // Create a scripting engine manager
        ScriptEngineManager manager = new ScriptEngineManager();
        // Obtain a Nashorn scripting engine from the manager
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            // Execute the script that will call the propTest() and arrayTest() methods of this class
            engine.eval("load('" + scriptFileName + "')");
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
    public static void propTest(ScriptObjectMirror point) {
        // List all properties
        System.out.println("Properties of point received in Java...");
        for (String prop : point.keySet()) {
            Object value = point.getMember(prop);
            System.out.println(prop + " = " + value);
        }
        // Let us add a property named z
        System.out.println("Adding z = 30 to point in Java... ");
        point.setMember("z", 30);
    }
    public static void arrayTest(ScriptObjectMirror empIds) {
        if (!empIds.isArray()) {
            System.out.println("Passed in object is not an array.");
            return;
        }
        // Get the length property of the array
        int length = ((Number) empIds.getMember("length")).intValue();
        System.out.println("empIds received in Java...");
        for (int i = 0; i < length; i++) {
            int value = ((Number) empIds.getSlot(i)).intValue();
            System.out.printf("empIds[%d] = %d%n", i, value);
        }
        // Let us add an element to the array
        System.out.println("Adding empIds[2] = 103 in Java... ");
        empIds.setSlot(length, 103);
    }
}
```
  • 在Java中创建Nashorn对象

    • 脚本文件 Point.js
      javascript // Point.js // Define the Point constructor function Point(x, y) { this.x = x; this.y = y; } // Override the toString() method in Object.prototype Point.prototype.toString = function() { return "Point(" + this.x + ", " + this.y + ")"; }; // Define a new method called distance() Point.prototype.distance = function(otherPoint) { var dx = this.x - otherPoint.x; var dy = this.y - otherPoint.y; var dist = Math.sqrt(dx * dx + dy * dy); return dist; };
    • Java文件 CreateScriptObject.java
      ```java
      // CreateScriptObject.java
      package com.jdojo.script;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.nio.file.Paths;
      import javax.script.ScriptEngine;
      import javax.script.ScriptEngineManager;
      import jdk.nashorn.api.scripting.ScriptObjectMirror;

    public class CreateScriptObject {
    public static void main(String[] args) {
    // Construct the script file path
    String scriptFileName = “point.js”;
    Path scriptPath = Paths.get(scriptFileName);
    // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
    if (! Files.exists(scriptPath) ) {
    System.out.println(scriptPath.toAbsolutePath() + ” does not exist.”);
    return;
    }
    // Get the Nashorn script engine
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName(“JavaScript”);
    try {
    // Execute the script in the file
    engine.eval(“load(‘” + scriptFileName + “’);”);
    // Get the Point constructor as a ScriptObjectMirror object
    ScriptObjectMirror pointFunc = (ScriptObjectMirror)engine.get(“Point”);
    // Create two Point objects. The following statements are the same as var p1 = new Point(10, 20); and var p2 = new Point(13, 24); in a Nashorn script
    ScriptObjectMirror p1 = (ScriptObjectMirror)pointFunc.newObject(10, 20);
    ScriptObjectMirror p2 = (ScriptObjectMirror)pointFunc.newObject(13, 24);
    // Compute the distance between p1 and p2 calling the distance() method of the Point object
    Object result = p1.callMember(“distance”, p2);
    double dist = ((Number)result).doubleValue();
    // Get the string forms of p1 and p2 by calling their toString() method
    String p1Str = (String)p1.callMember(“toString”);
    String p2Str = (String)p2.callMember(“toString”);
    System.out.printf(“The distance between %s and %s is %.2f.%n”, p1Str, p2Str, dist);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    - **从Java调用脚本函数**: - **脚本文件**:`factorial.js` javascript
    // factorial.js
    // Returns true if n is an integer. Otherwise, returns false.
    function isInteger(n) {
    return typeof n === “number” && isFinite(n) && n%1 === 0;
    }
    // Define a function that computes and returns the factorial of an integer
    function factorial(n) {
    if (!isInteger(n)) {
    throw new TypeError(“The number must be an integer. Found:” + n);
    }
    if(n < 0) {
    throw new RangeError(“The number must be greater than 0. Found: ” + n);
    }
    var fact = 1;
    for(var counter = n; counter > 1; fact *= counter–);
    return fact;
    }
    - **Java文件**:`InvokeScriptFunctionInJava.java` java
    // InvokeScriptFunctionInJava.java
    package com.jdojo.script;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import jdk.nashorn.api.scripting.ScriptObjectMirror;

    public class InvokeScriptFunctionInJava {
    public static void main(String[] args) {
    // Construct the script file path
    String scriptFileName = “factorial.js”;
    Path scriptPath = Paths.get(scriptFileName);
    // Make sure the script file exists. If not, print the full path of the script file and terminate the program.
    if (!Files.exists(scriptPath)) {
    System.out.println(scriptPath.toAbsolutePath() + ” does not exist.”);
    return;
    }
    // Get the Nashorn script engine
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName(“JavaScript”);
    try {
    // Execute the script in the file, so the factorial() function is loaded
    engine.eval(“load(‘” + scriptFileName + “’);”);
    // Get the reference of the factorial() script function
    ScriptObjectMirror factorialFunc = (ScriptObjectMirror)engine.get(“factorial”);
    // Invoke the factorial function and print the result
    Object result = factorialFunc.call(null, 5);
    double factorial = ((Number) result).doubleValue();
    System.out.println(“Factorial of 5 is ” + factorial);
    / Call the Array.prototype.join() function on a String object /
    // Get the reference of the Array.prototype.join method
    ScriptObjectMirror arrayObject = (ScriptObjectMirror)engine.eval(“Array.prototype”);
    ScriptObjectMirror joinFunc = (ScriptObjectMirror)arrayObject.getMember(“join”);
    // Call the join() function of Array.prototype on a string object passing a hyphen as a separator
    String thisObject = “Hello”;
    String separator = “-“;
    String joinResult = (String)joinFunc.call(thisObject, separator);
    System.out.println(joinResult);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    - **脚本日期转换为Java日期**: - **Java文件**:`ScriptDateToJavaDate.java` java
    // ScriptDateToJavaDate.java
    package com.jdojo.script;
    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import jdk.nashorn.api.scripting.ScriptObjectMirror;

    public class ScriptDateToJavaDate {
    public static void main(String[] args) {
    // Get the Nashorn script engine
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName(“JavaScript”);
    try {
    // Create a Date object in script
    ScriptObjectMirror jsDt = (ScriptObjectMirror)engine.eval(“new Date()”);
    // Get the string representation of the script date
    String jsDtString = (String) jsDt.callMember(“toString”);
    System.out.println(“JavaScript Date: ” + jsDtString);
    // Get the epoch milliseconds from the script date
    long jsMillis = ((Number) jsDt.callMember(“getTime”)).longValue();
    // Convert the milliseconds from JavaScript date to java Instant
    Instant instant = Instant.ofEpochMilli(jsMillis);
    // Get a ZonedDateTime for the system default zone id
    ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
    System.out.println(“Java ZonedDateTime: ” + zdt);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
    ```

通过上述总结,我们可以清晰地看到Java与Nashorn脚本交互的各种场景和实现方式。在实际开发中,合理运用这些API和方法,结合NetBeans IDE的调试、追踪和性能分析功能,能够高效地开发和优化基于Nashorn脚本的应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值