我正在构建一个Clojure Noir Web应用程序,以便在CloudFoundry中作为WAR文件运行。
在我的project.clj中,我有:
:ring {:handler appname.server/handler}
在server.clj中,我使用Noir创建一个处理程序:
(def handler (noir.server/gen-handler {:ns 'appname}))
我使用lein ring插件构建WAR文件:
lein ring uberwar
然后使用:
推送到CloudFoundryvmc push appname
请求处理程序正常工作,我可以浏览到应用程序的URL。
所以问题是:启动应用程序时进行初始化的正确方法是什么?
我可以在server.clj中执行以下操作:
(when (System/getenv "VCAP_APPLICATION")
(init-func))
但是有一些问题。首先,似乎是在错误的时间进行初始化(当读取/评估代码而不是在应用程序启动时)。其次,保护器特定于CloudFoundry,我确定有一个适当的一般WAR方式来做到这一点。
我认为这是ServletContextListener上contextInitialized方法的目的但是如何用Noir / ring挂钩呢?
答案 0 :(得分:6)
通过查看ring source for WAR handling
来计算出来project.clj:ring map采用:init关键字,如下所示:
:ring {:init appname.server/my-init
:handler appname.server/handler}
将在应用程序启动时调用my-init函数。
警告:这显然会增加应用程序初始启动所需的内存量。没有初始化,128M就足够了。使用初始化代码,应用程序启动失败,因此我不得不将内存增加到256M。我怀疑使用init代码时,JVM在编译/执行Clojure代码之前没有时间进行垃圾收集。