如何在Apache中集成Clojure Web应用程序

56

注意

考虑到这篇原始文章是大约两年前写的,我想知道是否存在逐步说明的指令,以便我可以将一个Noir或其他Clojure Web应用程序集成到Apache中,无论是Jetty、Tomcat还是其他什么东西。类似的指令存在于Django中,我认为我明白Python在Django的情况下被运行为引擎而不是ring框架,因此Clojure web应用程序更加复杂。

结束注释

我深深地爱着Clojure,而Compojure似乎是一个很棒的Web框架。

但当我想将我的应用程序作为WAR在像Tomcat这样的常规应用程序服务器上部署时,一切都崩溃了。我实际上必须编写自定义的Ring处理程序来处理静态文件和资源,使其在本地Jetty和Tomcat上都能工作,因为标准处理程序不能正常工作,并且我必须手动在每个位置添加上下文根。

我感到非常惊讶,因为我必须编写所有这些代码来创建最简单的Web应用程序,它既可以在Jetty上运行又可以在Tomcat上运行。对于这一点,我只有三个可能的解释:

  1. 没有人将Clojure/Compojure用于除了在本地Jetty上进行开发之外的任何事情,即生产
  2. 每个人都在专用的Jetty上部署Clojure/Compojure应用程序而不需要上下文根(就像人们对Node.js应用程序所做的那样)
  3. 存在一种非常简单的方法来绕过我遇到的问题,我不知道

在您看来,这些哪一种情况是适用的?还是其他什么情况?

编辑:

请注意,使用Maven/Leiningen创建war文件是轻而易举的,并不是我的意思。我想知道为什么我必须编写如此多的代码才能使Compojure与Tomcat配合工作,例如静态文件服务和上下文根感知,这些基本的东西应该可以开箱即用。


4
我非常感兴趣了解这个问题的结果。 - Stone Mason
我回答中附带的蛋糕项目模板解决了从Jetty和Tomcat两个服务器中提供应用程序的问题。 - mac
7个回答

11

我使用以下组合来使这个过程相对轻松:

Cake(包括部署命令)

一个由Lau Jensen开发的用于Web项目的Cake模板。

Vagrant(Ruby虚拟机(Virtualbox)管理工具,依赖于Chef或Puppet)

VPS(来自Slicehost)

关键部分是Lau制作的webdev模板。 webdev文件夹应放置在~/.cake/templates中。要基于它创建新项目,请使用:

cake new webdev *projectname*

请注意,该模板包含log4j和Java邮件,如果不需要可以排除。它进一步假定您正在使用Enlive和Moustache,但如果您喜欢Compojure/Hiccup,更改也很容易。
该模板负责在开发中从jetty提供应用程序(只需评估server.clj),并在Tomcat下运行时作为war工作。如果将其部署到Tomcat下的ROOT.war,路由保持不变。所有静态文件都应该位于资源目录中。Jetty将从那里提供它们(感谢Ring文件中间件)。在生产中,这些文件被移动到Web应用程序的根目录,并由Tomcat从那里提供服务(web.xml会处理这个问题)。
devbox文件夹包含一个Vagrantfile和必要的cookbooks,可创建安装了Tomcat的Virtualbox VM。我使用cake将.war文件部署到/home/vagrant目录中(这是通过project.clj中定义的dev上下文来控制的)。.war文件被符号链接到Tomcat的webapps目录(/var/lib/tomcat6/webapps)中作为ROOT.war。有关如何使用Vagrant的更多信息,请参见Vagrantsite
这个gist展示了如何调整project.clj以使用cake deploy命令的示例。该示例创建了两个上下文@dev和@prod,您可以使用以下命令进行部署:
cake deploy @dev / cake delpoy @prod

我已经将Cake webdev模板和Vagrant文件收集在这个zip中。


1
webdev 应该是类似于这个的一系列配方中的第一个:https://github.com/klang/cake-recipes。 - klang
谢谢 - 不知何故,提问者似乎不同意 :-) - mac

9

请看我对stand的回答的评论。 - futlib
之前的无知真是抱歉,混淆了lein-ring和leiningen-war。lein-ring确实很棒,可以满足我所有的需求:lein ring server启动Jetty,lein ring uberwar构建一个在Tomcat中不需要任何路由修改就能正常工作的war包。我希望Maven也有类似的功能,但现在我已经转向Leiningen了。 - futlib

6
我已经成功地使用 leiningen-war生成了一个通用的war文件(当然,假设你正在使用leiningen)。它允许您在project.clj文件中指定静态html的位置、web.xml的位置和其他资源的位置。对于我来说,生成一个我能够部署到JBoss(运行Tomcat作为servlet容器)的通用war文件并不太困难,但我认为你必须对web.xml格式非常熟悉。我更喜欢自己编写web.xml,因此可能更喜欢这种方法。
看起来,leiningen-war背后的人现在推荐lein-ring。我已经开始研究它,但到目前为止,我还没有像之前那样轻松地从它那里获得一个通用的war文件。
不过,我同意在生产部署方面存在一些弱点。

创建war文件对我来说不是问题,我使用Maven非常简单。但是调整我的应用程序以处理应用服务器问题,例如静态文件服务和上下文根,需要太多的工作。 - futlib

3

我正在使用Noir,这是一个建立在Ring和Compojure之上的Web框架。

我使用lein noir new my-proj创建了项目。然后我创建了my-proj/web目录,并将以下行添加到其中:

project.clj:    
    :compile-path "web/WEB-INF/classes"
    :library-path "web/WEB-INF/lib"
    :ring {:handler project.server/handler}

我在Tomcat开发期间将my-proj/web目录设置为上下文根。
对于静态文件服务,我将内容放在my-proj/resources/public目录下。 要通过代码访问(读写)文件,可以使用ring请求头中的:servlet-context。在上述设置中,上下文路径为:(.getRealPath (ring-request-header :servlet-context) "/WEB-INF/classes/myfile.txt")。Myfile.txt位于my-proj/resources下。

2
如果您正在部署到Google App Engine,这是一篇非常好的博客:http://compojureongae.posterous.com/。即使您没有部署到GAE上,仍然可以从中获得一些有用的技巧。

这个例子似乎启动了自己的Jetty。那么这是常见情况吗? - futlib

2
我已经在生产环境中发布了一个Compojure+Vaadin应用程序(已经超过6个月了)。使用lein-war插件进行打包,我没有遇到任何重大问题。
该应用程序名为halo,包含在一个halo.war文件中,上下文为/halo,Tomcat服务器还运行着Hudson和另一个定制的应用程序。Vaadin正确解析了所有静态文件,如CSS、图像等。我主要使用博客文章来编写所需的少量粘合剂。
另外,我也在Heroku上运行Noir,在打包和部署方面也没有遇到任何问题,这也是在生产环境中。
虽然这与你的Compojure问题没有直接关系,但Clojure在Web应用程序中的生产环境中绝对可行。

1
如果您正在使用基于环形的服务器(compojure、noir/lib-noir、luminus等),并且想要部署为uberjar,以避免...
"Failed to load Main-Class manifest attribute from your-uberjar.jar"

只需使用lein ring uberjar创建UberJar。请注意在lein uberjar后面添加'ring'。这是假设您正在使用lein-ring插件。


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