如何从Java中调用Node.js函数

4

我希望能够从Java中调用Node.js函数:

以下是我的hello.js JavaScript代码:

function myFun(param)
{
     console.log("hello"+param);
}

这是我的Java代码:

public static void main(String[] args) throws IOException {
  Process process = new ProcessBuilder("C:\\Program Files\\nodejs\\node.exe","hello.js").start();
  InputStream is = process.getInputStream();
  InputStreamReader isr = new InputStreamReader(is);
  BufferedReader br = new BufferedReader(isr);
  String line;
  
  
  while ((line = br.readLine()) != null) {
    System.out.println(line);
  }
    }

使用这段Java代码,我能执行hello.js文件,但我想从Java代码中调用myFun函数并设置该函数中的参数...这可能吗。


2
当您启动节点程序时,可以通过命令行参数将其传递给该程序,并根据这些命令行参数执行某些操作。或者,您可以启动一个服务器并从Java与该服务器通信。或者,您可以通过stdin发送一些内容。但是,您的Java无法直接访问节点程序的内部,因此必须使用现有的通信机制之一或自己构建新的通信机制。 - jfriend00
我可以使用流程构建器完成这个吗? - Be Technical
3个回答

2
您可以使用GraalVM在Java中调用node.js函数。
GraalVM提供了一个多语言运行时环境,其发行版包括JDK和node。
您可以在Java中执行JavaScript,将JavaScript上下文嵌入到Java程序中,例如:
import org.graalvm.polyglot.*;
import org.graalvm.polyglot.proxy.*;

public class HelloPolyglot {

    static String JS_CODE = "(function myFun(param){console.log('hello '+param);})";

    public static void main(String[] args) {
        System.out.println("Hello Java!");
        try (Context context = Context.create()) {
            Value value = context.eval("js", JS_CODE);
            value.execute(args[0]);
        }
    }
}

请注意函数定义周围的(),我只想让它立即返回函数。您可以使用其他方式,不仅限于字符串中的代码,还可以使用文件、模块等。
并在PATH上使用GraalVM运行它:
❯ javac HelloPolyglot.java
❯ java HelloPolyglot StackOverflow
Hello Java!
hello StackOverflow

尽管这个问题不一定需要,但是这里有一个Value类的Javadoc,这样你就可以使用多语言值。
这样你就可以使用JavaScript。它没有像node.js那样提供平台功能,如节点事件循环、文件系统访问等,node是一个单独的平台,将其嵌入到JVM进程中有些棘手。
你可以做的是启动node进程,它会启动JVM。
想象一下你有一个名为app.js的应用程序。
var HelloPolyglot = Java.type("HelloPolyglot");

HelloPolyglot.main(["from node.js"]);

console.log("done");

您可以使用GraalVM node运行以下命令:
❯ node --jvm --vm.cp=. app.js
Hello Java!
hello from node.js
done

请注意,我们传递了--jvm以使用JVM启动它(否则就没有能力运行Java),并将Java程序的类路径传递给节点,以便它知道如何正确启动JVM。
然后,节点和JVM在同一个进程中运行,并且使用与上述相同的Value类来进行交互。

1
这并不容易。你有几种可能的方法来做到这一点:
  1. 使用JNI绑定到V8(Node.js只是带有大型库和一些粘合剂的V8)。
  2. 使用ProcessBuilder并传递参数。
  3. (这不完全是你要求的)使用Java编写的Javascript引擎(GraalVM

优缺点

  1. 具有优势,可以提供更多控制(==>更灵活),但编写JNI很难、容易出错且耗时。
  2. 是最简单的解决方案,但不太灵活。
  3. 也许是另一种解决方案,可能优于1.(无需发送本机库)和2.(非常脆弱,因为需要一个特定的node.exe位置)。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接