如何从java调用Nodejs函数

如何从java调用Nodejs函数,java,node.js,Java,Node.js,我想从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 Fi

我想从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文件,但我想调用myFun函数,并从java代码中设置此函数中的参数。。有没有可能做到这一点。

没那么容易。您有几种可能的方法可以做到这一点:

  • 使用JNI绑定到V8(Node.js只是一个带有大型库和一些胶水的V8)
  • 使用ProcessBuilder并传递参数
  • (这不完全是您要求的)使用Java()编写的Javascript引擎
  • 赞成/反对

  • 它的优点是,它可以为您提供很多控制(=>更灵活),但是编写JNI很难,容易出错,而且耗时
  • 是最简单的解决方案,但没有那么灵活
  • 可能是另一种解决方案,它可能优于1。(无需提供本机库)和2。(非常脆弱,因为您需要node.exe的特定位置)

  • 您可以使用GraalVM从java调用node.js函数

    GraalVM为您提供了一个polyglot运行时,该发行版包括一个JDK和一个节点

    您可以从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]);
            }
        }
    }
    
    注意
    ()
    包装函数定义,我只希望它立即返回函数。您可以使用文件、模块等,而不仅仅是字符串中的代码

    并在
    路径上使用GraalVM运行它

    ❯ javac HelloPolyglot.java
    ❯ java HelloPolyglot StackOverflow
    Hello Java!
    hello StackOverflow
    
    虽然这对于这个问题不是绝对必要的,但这里有一些方法,您可以使用polyglot值

    这样您就可以使用JavaScript了。它不具备节点事件循环、fs访问等平台功能,
    node.js
    是一个独立的平台,很难将其嵌入JVM进程

    您可以做的是启动节点进程,这将启动JVM

    假设你有一个像
    app.js

    var HelloPolyglot = Java.type("HelloPolyglot");
    
    HelloPolyglot.main(["from node.js"]);
    
    console.log("done");
    
    然后可以运行(使用GraalVM节点):

    请注意,我们传递
    --jvm
    以使用jvm启动它(否则就没有执行Java的能力),并将Java程序的类路径传递给节点,以便它知道如何正确启动jvm


    然后节点和JVM都在同一个进程中运行,互操作使用与上述相同的
    类进行工作。

    我建议,它允许您将node.js运行时嵌入java应用程序。

    您可以在启动节点程序时将命令行参数传递给节点程序,并让启动代码根据这些命令行参数执行某些操作。或者,您可以启动一个服务器并从Java与该服务器通信。或者你可以通过stdin发送一些东西。但是,您的Java无法直接访问节点程序的内部,因此您必须使用现有的通信机制之一,或者自己构建一个新的通信机制?
    ❯ node --jvm --vm.cp=. app.js
    Hello Java!
    hello from node.js
    done