Uberjar使用Lein Ring构建,但无法识别配置文件中的环境变量

4
在我的Leiningen项目.clj文件中,我使用 environ在不同的配置文件中设置环境变量。我想要使用lein-ring构建一个演示uberjar,该演示版本使用某些环境变量的不同值来替换生产版本。然而,出于某种原因,我似乎无法获取它们。
我在项目.clj文件中定义了一个名为demo的配置文件,类似于以下内容:
:demo {:dependencies [[javax.servlet/servlet-api "2.5"]]
       :plugins [[lein-environ "0.4.0"]]
       :env {:foo "FOO" :bar "BAR"}}

然后我执行

lein with-profile demo ring uberjar

但是在生成的独立jar包中,使用environ.core/env访问foo或bar会返回nil。另一方面,如果我运行

lein with-profile demo ring server-headless

我可以访问两者的值。
为什么会这样?这真的不是我所期望的。看起来uberjar总是使用生产配置创建。或者还有其他问题吗? lein-ring页面确实说明了以下内容:
Lein-Ring关注多个环境变量,包括: PORT - Web服务器用于HTTP的端口SSLPORT - Web服务器用于HTTPS的端口
这些将覆盖在project.clj文件中指定的任何选项,但不会覆盖在命令行上指定的任何选项。
然而,这并不清楚是否意味着project.clj中指定的任何其他环境变量都将被忽略。
在Windows上运行leiningen 2.3.4。
1个回答

3
看起来 lein-environ 插件实际上并没有物理设置环境变量(事实上,您无法从 Java 内部设置当前进程的环境变量 - 有关详细信息,请参见这里)。即使它可以,也请问自己 - 您如何确保在构建 uberjar 时存在的环境变量在运行时也存在呢?
相反,lein-environ 和配套的 environ.core/env 函数为您提供了一种模拟环境变量以进行测试和开发的方法,而无需在启动 Leiningen 之前手动设置环境变量。插件代码将项目映射中提供的变量写入 .lein-env 文件,并在从项目代码调用 env 时将这些值与实际操作系统环境中的值合并。
当你运行uberjar时,实际上需要在Windows环境中存在这些变量(或者在当前目录中的.lein-env文件中,但我不建议这样做)。如果你的目标是提供一个独立的演示,使用预设的环境变量来控制某些应用程序行为,我会创建一个.cmd脚本与你的应用程序一起分发,该脚本将设置适当的环境变量,然后启动uberjar。

谢谢。我确实知道 Environ 的工作原理,但我并没有真正感觉它只是用于测试。我知道网站上说在生产环境中你会替换为操作系统环境变量,但我一直把 Environ 视为我想在生产环境中使用的东西,作为配置不同构建的好方法。通过脚本设置这些演示变量的想法是可以接受的妥协,我也可以通过 Java 系统属性来设置它们。 - ChrisM
1
你可以采用类似的方法,将属性写入资源文件并捆绑在uberjar中,而不是写入文件系统,但这需要一些自定义代码。然而,任何直接使用System/getenv检查环境变量的代码都不会受到在lein-environ中设置的属性的影响。 - Alex
1
此外,environ.core 完全适用于生产环境。但是,你不应该期望通过 lein-environ 设置的属性在项目代码中可见,除非它作为 Leiningen 任务执行时。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接