是否可以让 Nashorn 从类路径加载脚本?

Is it possible to have Nashorn load scripts from classpath?

是否可以让 Nashorn 的 load 方法在解析 URI 时使用项目的类路径?

这是我正在尝试做的事情:

(defn create-engine
  "Creates a new nashorn script engine and loads dependencies into its context."
  [dependencies]
  (let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")
        scripts (map #(str "load('" % "');") dependencies)]
    (.eval nashorn "var global = this;")
    (doseq [script scripts] (.eval nashorn script))
    nashorn))

(def app "public/javascripts/app.js") ; in /resouces, on classpath


; resulting exception:
clojure.lang.Compiler$CompilerException: 
javax.script.ScriptException: TypeError: 
Cannot load script from public/javascripts/app.js in <eval> at line number 1

绝对路径应始终以斜杠开头,"/public/javascripts/app.js",但我不确定 load() 是否从 class 路径加载,如果不是,您可能有使用 eval(Reader) 方法并自己构造 reader

编辑:

如果路径在 jar 中是绝对路径,则需要为 classpath 资源使用左斜线。没有斜杠表示相对于您从中调用它的特定 class。您应该为资源获取 InputStream 并评估 reader,在 Java 中它看起来像这样:

nashorn.eval (new InputStreamReader (getClass().getResourceAsStream("/public/javascripts/app.js")));

我不想将它翻译成 clojure,因为那注定会以失败告终。

编辑 2:

好吧,那就试试吧:

(defn create-engine
  "Creates a new nashorn script engine and loads dependencies into its context."
  [dependencies]
  (let [nashorn (.getEngineByName (ScriptEngineManager.) "nashorn")]
    (.eval nashorn "var global = this;")
    (doseq [dependency dependencies] (.eval nashorn (new InputStreamReader (.getResourceAsStream String dependency))))
    nashorn))

如果启动核war什么的我概不负责

Nashorn 的load() 方法实际上支持采用URL 前缀为classpath:。它将从类路径中加载该前缀之后的文件。查看源代码 - http://cr.openjdk.java.net/~sundar/8025629/webrev.01/src/jdk/nashorn/internal/runtime/Context.java.html 第 502 行。

你应该使用 clojure.java.io/resource

(def nashorn (.. (javax.script.ScriptEngineManager.) (getEngineByName "nashorn")))
(.eval nashorn (clojure.java.io/reader (clojure.java.io/resource "jvm-npm.js")))

确保在您的 lein 项目中配置了资源文件夹:

:resource-paths ["src/resources"]