我正在构建一个Clojure Noir web应用程序,以便在CloudFoundry中作为WAR文件运行。
在我的项目.clj中,我有:
:ring {:handler appname.server/handler}
在server.clj中,我使用Noir创建了一个处理程序:
(def handler (noir.server/gen-handler {:ns 'appname}))
我使用lein-ring插件构建了WAR文件:
lein ring uberwar
然后使用推送到CloudFoundry
vmc push appname
请求处理程序运行良好,我可以很好地浏览到应用程序的URL。
所以问题是:启动应用程序时,正确的初始化方法是什么
我可以在server.clj中执行以下操作:
(when (System/getenv "VCAP_APPLICATION")
(init-func))
但这也有几个问题。首先,这似乎是在错误的时间进行初始化(当代码被读取/eval'd而不是在应用程序启动时)。其次,保护程序是特定于CloudFoundry的,我确信有一种合适的通用WAR方法可以做到这一点。
我认为这就是ServletContextListener上contextInitialized方法的目的,但我如何将其与Noir/ring挂钩?
通过查看WAR处理的环源来解决这个问题
project.clj:ring映射采用了一个:init关键字,如so:
:ring {:init appname.server/my-init
:handler appname.server/handler}
myinit函数将在应用程序启动时调用。
Caveat:这显然增加了应用程序初始启动所需的内存量。128M在没有初始化的情况下就足够了。由于初始化代码,应用程序启动失败,所以我不得不将内存增加到256M。我怀疑使用init代码,JVM在编译/执行Clojure代码之前没有时间进行垃圾收集。