【问题标题】:Call java program from Node.js application从 Node.js 应用程序调用 java 程序
【发布时间】:2017-09-07 08:20:04
【问题描述】:

根据我的阅读,有几种方法可以在 node.js 应用程序中运行 java 文件。一种方法是生成一个子进程:(java 代码与依赖项一起打包在一个可执行文件jar 中。)

var exec = require('child_process').exec, child;    
child = exec('java -jar file.jar arg1 arg2',
      function (error, stdout, stderr){
        console.log('stdout: ' + stdout);
        console.log('stderr: ' + stderr);
        if(error !== null){
          console.log('exec error: ' + error);
        }
    });

另一种方法是使用java - npm 模块(link),它是JNI 的包装器(这将让我创建objects,设置和获取attributes,运行methods)。

在生产环境中,当我希望我的node.js (Express) 服务器调用java 程序(它只是将图像保存到本地目录)时,请告诉我哪种方法更好来实现这一点(就最佳实践而言)。此外,我需要将一长串arguments 传递给main 类,并且在命令行上执行此操作有点困难。我应该改为从输入文件中读取java 程序吗?

【问题讨论】:

  • 如果您的输入足够复杂,我建议创建代表您的输入数据的 POJO,并使用 Jackson YAML 工厂将您的输入反序列化为 JSON 或 YAML 文件(YAML 也会解析 JSON)。然后使用 Args4J 并接受 JSON 作为文件选项,并有一个输入选项,例如 -i,它告诉您从标准输入读取输入,以便可以从另一个程序输入 JSON。这让他们有一个模板,他们可以使用该模板进行简单的令牌替换,然后通过管道传输到您的程序。或者你可以从节点做同样的事情。
  • 进一步考虑,通过 stdout/stdin 将数据发送到 java 程序似乎是最有意义的。创建一个临时文件然后从 java 程序加载只是没有必要,并且会引入 IO 瓶颈

标签: java node.js express


【解决方案1】:

1) 如果您使用exec,您将运行整个程序,而如果您使用 JNI 接口,您将能够直接与 jar 中的库和类进行交互,并执行诸如调用单个函数或创建类的实例。但是,如果您不需要类似的东西,我认为使用exec 会简单得多,而且运行速度也会更快。听起来您只想将 Java 应用程序作为独立进程运行,并记录应用程序是成功完成还是出现错误。我会说最好只使用exec。以这种方式执行子进程对于调试也好得多,有时调试 JNI 错误可能非常困难。

2) 至于是否从文件中读取参数,是的,通常从某种文件中读取比直接传入参数更好。它不太容易出现人为错误(即每次都输入参数),并且更易于配置。如果像 QA 工程师这样的人只需要编辑配置文件来交换选项,他们就不需要了解你的整个代码库来测试它。我个人对我编写的每个 Java 程序都使用配置文件。

【讨论】:

    【解决方案2】:

    您可以使用部署工具包并通过 jnlp 运行 jar。 https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deployment_toolkit.html 通过 jnlp 运行 jar 的优势在于能够将参数从 javascript 传递到您的 jar。通过这种方式,您可以动态自定义您的 java 程序。

    【讨论】:

    • 我可以传递不是Strings 的参数(比如Array)吗?
    • 我刚刚尝试过。我通过了 ` ['asd', 'qwe', 'zxc'] ` 并将它作为逗号分隔的字符串“asd,qwe,zxc”接收,它可以很容易地用逗号分隔并转换为数组
    • 是的,但有些元素中也可以包含逗号。
    【解决方案3】:

    对于这种类型的问题,您需要通过以下方式解决:

    • 在我的语言/框架中是否有一种体面的方式来运行带有参数的进程
    • 有没有合适的方法来处理程序输出?

    根据经验,处理进程中的参数的一种体面方法是将它们作为(字符串)数组传递。这是有利的,因为您不必求助于不必要的字符串插值和操作。它也更具可读性,这是此问题设置的一个优点。

    处理输出的一种不错的方法是使用基于侦听器/事件的模型。这样,您可以适当地响应事件,而不是为 stderr 和 stdout 设置 if 块。同样,这使事情变得可读,让您以更可维护的方式处理输出。

    如果再深入一点,您还必须解决如何将环境变量注入目标程序的问题。例如,您将来可能希望使用调试器或使用更少的内存来运行 java,因此您的解决方案也需要满足这一点。

    这只是解决这种这类问题的一种方法。如果 node 是您的平台,请查看支持所有这些技术的 Child Process。

    【讨论】:

      【解决方案4】:

      我们可以通过制作 .jar 文件来运行整个 java 项目,然后使用 shell 中的命令运行它并运行该 shell 文件。为了从 nodejs 项目运行 java 代码,我们知道项目可以是 java、js 模块的混合。 在 node 中调用 exec() 函数来创建一个子进程来执行具有运行 .sh 文件的命令的 shell 文件,也可以从 use.eg 中传递一些参数;

      let fileName = 'someFile.txt';
      let userName = 'Charlie Angle'; 
      exec(`sh run.sh --context_param
      paramFilePath="./storage/${fileName}" --context_param userName="${userName}"`, (error, stdout, stderr) => {// Some code based on execution of above command})
      

      【讨论】:

        【解决方案5】:

        您可以使用模块 node-java-caller 简单地调用带有类路径和参数的 java 命令,它会嵌入对 spawn 的调用,并且如果系统上不存在 java,它也会自动安装 java

        https://github.com/nvuillam/node-java-caller

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-11-09
          • 1970-01-01
          • 2018-07-03
          • 1970-01-01
          • 2013-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多