Clojure应用程序中的资源

Kev*_*cht 52 clojure leiningen

我在我的Clojure项目(GUI应用程序)中使用Leiningen,并在项目根目录下创建了一个"resources"目录来保存我的应用程序使用的图像.

当我在测试期间在本地运行我的应用程序时,我使用相对路径"resources/logo.png"获取图像,这样可以正常工作.但是当我使用Leiningen构建一个uberjar时,Leiningen将来自资源文件夹的文件放在JAR的根文件夹中,因此我对资源文件的引用不再起作用.

使用Leiningen访问这样的资源的正确方法是什么?

Kev*_*cht 46

之前的回答者(skuro)指出我需要从类路径中获取文件.经过一番挖掘后,这似乎是适合我案例的解决方案:

(.getFile (clojure.java.io/resource "foo.png"))
Run Code Online (Sandbox Code Playgroud)

  • `(.getPath)`更准确,因为`(.getFile)`还附加了可能不存在于资源URL中的现有查询参数. (6认同)

Val*_*ora 30

只是Kevin Albrecht答案的语法糖:

(require '[clojure.java.io :as io])

(-> "foo.png" io/resource io/file) 
Run Code Online (Sandbox Code Playgroud)

  • 在任何人开始啜饮文件之前,请注意,一旦打包在jar中,这将无法正常工作.slurp可以在资源本身上运行:http://stackoverflow.com/questions/32232662/clojure-uberjar-not-loading-resource-file (3认同)

sku*_*uro 14

Leiningen从maven借用了资源约定,文件夹布局略有不同.规则规定该resources文件夹必须用作编译时类路径根,这意味着leiningen正确地将文件resources夹中的所有文件放在jar中的根位置.

问题是物理位置!=类路径位置,所以当你打包应用程序时前者改变,后者保持不变(classpath:/)

您最好依靠类路径位置来查找文件系统资源,或者将它们从jar中取出并将它们放入可预测的文件夹中,可以是静态文件夹,也可以是可配置文件夹.


Dan*_*yes 14

这并没有直接回答OP的问题,但是skuro在他的最后一段中提到了一些非常有用的东西,即在开发过程中在类路径上提供资源,但不包括在发布jar/uberjar中.

这样做的原因是你可以将资源单独放在jar之外 - 例如将配置文件放在/etc- 然后在运行时通过在类路径上列出这些资源文件夹链接到它们.

project.clj中的定义

  • :resource-paths从project.clj中删除顶级;
  • 在顶层的project.clj中添加以下行:
:profiles {:dev {:resource-paths ["src/main/resources"]}}
Run Code Online (Sandbox Code Playgroud)

这样,在开发(编译,测试,repl)期间,资源将在类路径上可用,但不会包含在发布jar中.

作为一个替代方案,您可能希望将一些资源与发布jar捆绑在一起,如应用程序图标和图形,而不是其他资源,如配置文件.在这种情况下,您可以将resources文件夹拆分为子目录,并声明要包含在顶层的那些文件夹,而在dev配置文件下的其余部分:

:resource-paths ["src/main/resources/icons"
                 "src/main/resources/images"]
:profiles {:dev {:resource-paths ["src/main/resources/config"]}}
Run Code Online (Sandbox Code Playgroud)

引用代码中的资源

使用上面的方法,你可以在开发和生产过程中通过在类路径上查看资源(如KevinValerii所示)来引用资源,而不是直接在文件系统上:

(require '[clojure.java.io :as jio])
(jio/file (jio/resource "relative/path/to/resource.xml"))
Run Code Online (Sandbox Code Playgroud)

运行时类路径

在开发过程中,Leiningen将包括dev类路径中的顶级资源和配置文件资源.对于已发布的运行时,您必须自己配置JRE的类路径:

java -cp "/etc/myapp:/usr/local/lib/myapp.jar" myapp.core $*
Run Code Online (Sandbox Code Playgroud)

另外,您可以实际上保留jar中包含的所有资源.这样,包含的资源将用作默认值.如果设置类路径以使.jar文件位于配置文件夹之后(/etc/myapp在示例中),则配置文件夹下具有相同相对资源路径的资源文件将优先于jar中包含的资源文件.


Ada*_*old 5

我遇到了完全相同的问题,解决方案根本没有使用io/file。例如,这是我的应用程序中的工作代码:

(defn load-md [md]
  (->
   md
   io/resource ;;clojure.java.io
   slurp
   mp
   to-hiccup
   html))
Run Code Online (Sandbox Code Playgroud)