我应该如何从 Java 应用程序运行 NodeJS? [英] How should I run NodeJS from a Java application?

查看:36
本文介绍了我应该如何从 Java 应用程序运行 NodeJS?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个 Java 库,实际上是一个 Clojure 库,但对于这个问题,重要的是它在 JVM 上运行.这个库需要执行一些 JavaScript.我试过 Nashorn 但我遇到了一些可能难以克服的限制.作为替代方案,我想尝试使用 NodeJS.

I'm writing a Java library, actually, a Clojure library, but for this question, what matters is that it runs on the JVM. This library needs to execute some JavaScript. I tried with Nashorn but I encounter some limitations that might be too hard to overcome. As an alternative, I want to try NodeJS.

我希望我的库是自包含的,不依赖于独立运行 NodeJS 的系统,因此需要一种特定的部署机制来将 Java 和 NodeJS 工件放置在正确的位置,以便两个不同的网络服务器获取.但是,这种方法会带来一些问题.

I want my library to be self contained, to not depend on the system running NodeJS independently and thus requiring a particular deployment mechanism to place the Java and NodeJS artifacts in the right places to be picked up by the two different network servers. This approach, though, brings some issues.

我将通过 HTTP 与 NodeJS 交谈,但我不希望 NodeJS 打开特定端口.我想找到一个随机未使用的,这样就不会发生冲突.我还想控制来自 NodeJS 的日志的去向,以便将它们保留在我的应用程序的其余部分中.最后,我的应用应该能够检测到 NodeJS 何时崩溃并重新运行它或报告错误信息.

I will be talking to NodeJS over HTTP but I don't want NodeJS to open a specific port. I want to find a random unused one so there's no collisions. I also want to control where the logs from NodeJS go, as to keep them with the rest of my application. Lastly, my app should be able to detect when NodeJS crashed and re-run it or report an error with information.

解决这个问题的最佳方法是什么?是否有任何 Java 库可以帮助以这种方式管理子进程?我应该从 NodeJS 方面做任何特别的事情(我对 NodeJS 很陌生,我以前从未使用过它).

What's the best way to approach this? Are there any Java libraries to help manage child process in this fashion? Anything in particular I should do from the NodeJS side (I'm very new to NodeJS, I never used it before).

推荐答案

我最终的解决方案是这样使用ProcessBuilder:

My solution in the end was to use ProcessBuilder like this:

(defn create-process-builder [js-engine]
  (doto (ProcessBuilder. ["node" (:path js-engine)
                          "--port-file" (:port-file js-engine)
                          "--default-ajax-host" (:default-ajax-host js-engine)
                          "--default-ajax-port" (str (:default-ajax-port js-engine))])
    .inheritIO))

然后在里面调用 start .继承IO导致它的输出转到当前进程的输出,这有效地合并了stdout和stderr.

and then call start in it. inheritIO causes the output of it to go to the output of the current process which effectively merges stdout and stderr.

在此基础上,NodeJS 通过指定 0 作为端口号打开一个随机端口并将其写入文件:

On top of that NodeJS opens a random port by specifying 0 as the port number and writes it to a file:

(let [app (-> (express)
              (.use (cookie-parser))
              (.get "/" (fn [_req res] (.send res "Universal JavaScript engine for server side pre-rendering single page applications.")))
              (.get "/render" render))
      server (.createServer http app)]
  (.listen server 0 (fn [] (.writeFile fs (:port-file options) (.-port (.address server)))))))))

然后由Java端打开(等待它出现):

which then is opened by the Java side (waiting for it to appear):

(defn get-port-number [js-engine]
  (or (with-timeout
        (:start-timeout js-engine)
        (loop [port-number (read-port-file js-engine)]
          (if (string/blank? port-number)
            (if (is-running? js-engine)
              (do (Thread/sleep 100)
                  (recur (read-port-file js-engine)))
              (throw (Exception. (str "While waiting for port number, process died: " (:path js-engine)))))
            port-number)))
      (throw (Exception. (str "Waited for " (:start-timeout js-engine) " for " (:path js-engine) " to start and report its port number but it timed out.")))))

这篇关于我应该如何从 Java 应用程序运行 NodeJS?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆