如何使用Clojure创建Web应用程序?

219

对于每天都在使用Java的绝大多数程序员来说,我想这可能是一个奇怪的问题。但我并不是那样。虽然我接触过Java语言并参与过Java项目,但并不熟悉Java技术栈。我从未使用Java从头开始构建Web应用程序。如果我需要使用Python或Ruby来构建Web应用程序,我会选择Django或Rails这样的框架,但如果我想使用Clojure构建Web应用程序,不是因为我被迫生活在Java世界中,而是因为我喜欢这门语言,想尝试一下,那我该使用哪些库和框架呢?


1
我想知道你是否希望使用Java Native API还是Clojure Native API? - Ande Turner
Pupeno!我是通过搜索“使用Clojure开发Web应用程序”而来到这里的。这个页面是在谷歌中排名第一的结果。 - Sebastián Grignoli
2
请注意相关问题https://dev59.com/rHA75IYBdhLWcg3wYX9Q - Petr Gladkikh
记事本(emacs):完成。不刮胡子:完成。男人模式:开启 - Adam Arold
@AdamArold:你是认真地把Emacs和记事本比较了吗?像,真的吗?! - mike3996
显示剩余4条评论
16个回答

180

Compojure不再是一个完整的用于开发web应用程序的框架。自从0.4版本发布以来,compojure已经被拆分成了几个项目。

Ring提供了基础功能,将HTTP请求和响应过程抽象化。Ring会解析传入的请求并生成包含请求中所有部分(例如uri、server-name和request-method)的映射。然后应用程序将处理该请求并根据请求生成响应。响应表示为包含以下键的映射:状态(status)、标头(headers)和正文(body)。因此,一个简单的应用程序看起来像:

(def app [req]
  (if (= "/home" (:uri req))
    {:status 200
     :body "<h3>Welcome Home</h3>"}
    {:status 200 
     :body "<a href='/home'>Go Home!</a>"}))

Ring的另一个部分是中间件的概念。这是介于处理程序和传入请求/传出响应之间的代码。一些内置的中间件包括sessions和stacktrace。 session中间件将向请求映射中添加一个:session键,其中包含发出请求的用户的所有会话信息。 如果响应映射中存在 :session键,则会将其存储为当前用户的下一个请求。 而堆栈跟踪中间件将捕获在处理请求时发生的任何异常,并生成一个堆栈跟踪作为响应发送回来,如果确实发生了任何异常。

直接使用Ring进行工作可能很繁琐,因此Compojure是建立在Ring之上的,抽象掉了细节。现在可以通过路由来表达应用程序,所以您可以像这样:

(defroutes my-routes
  (GET "/" [] "<h1>Hello all!</h1>")
  (GET "/user/:id" [id] (str "<h1>Hello " id "</h1>")))

Compojure仍然使用请求/响应映射,因此如果需要,您始终可以访问它们:

(defroutes my-routes
  (GET "*" {uri :uri} 
           {:staus 200 :body (str "The uri of the current page is: " uri)}))
在这种情况下,{uri :uri} 部分访问请求映射中的 :uri 键,将 uri 设置为该值。
最后一个组件是 Hiccup,它使生成HTML更容易。各种HTML标签表示为向量,其第一个元素表示标签名称,其余部分则是标签内容。"

A header

" 变为 [:h2 "A Header"]。标签的属性包含在可选的映射中。"Log In Page" 变为 [:a {:href "/login"} "Log In Page"]。这里有一个使用模板生成HTML的小例子。
(defn layout [title & body]
  (html
    [:head [:title title]]
    [:body [:h1.header title] body])) 

(defn say-hello [name]
  (layout "Welcome Page" [:h3 (str "Hello " name)]))

(defn hiccup-routes
  (GET "/user/:name" [name] (say-hello name)))

这里有一个链接,指向compojure的作者正在编写的一份文档,可能会对您有所帮助: Compojure Doc


105
到目前为止,我遇到的最好的Clojure Web框架是Compojure:http://github.com/weavejester/compojure/tree/master 它小而强大,并且具有优美的语法。(它在内部使用Jetty,但除非您需要它,否则它会将Servlet API隐藏起来,这不会经常发生)。请访问该网址上的README,然后下载快照并开始使用。

17
理查德的评论是针对这个回答的吗?我不理解它。 - John Cromartie
27
@Richard,你的观点相当可笑。是的,如果你决定使用Java库,在许多情况下你会失去函数式编程的优势。但这些库的目的在于让你永远不必再做同样的事情。例如,Ring是一个Clojure封装了Servlets的库,所以你不必直接使用Servlets。你是否建议我们重新发明Web开发轮子,而不是使已经完美的Java工具更易用于Clojure?这样做的逻辑在哪里呢?此外,有可选使用这些库又有何不妥之处呢?... - Rayne
16
你的整个论点暗示着非功能性的非Clojure代码本质上是如此糟糕,以至于即使它隐藏在库的下面,也是一种污染。我不理解这个推理。许多Java库是有用且强大的代码片段。为什么要从头开始重写它们,当我们可以简单地提供自己的包装库,使其能够从Clojure中优雅和功能性地使用呢? - Rayne
11
@Richard,请随意制作一个纯Clojure的HTTP服务器。 - gtrak
5
在Lisp/Clojure中,函数没有副作用。(参见http://www.gigamonkeys.com/book/they-called-it-lisp-for-a-reason-list-processing.html)。然而,正如《Lisp世界》所指出的那样(http://landoflisp.com/trade_func.png),一个纯函数式程序通常并不是非常有用的,因为副作用是实际上执行任务所必需的,比如写数据库记录、下载文件、向REST服务器发布信息、生成图像等等... - lfalin
显示剩余6条评论

49

还有一个名叫"Noir"的框架(http://www.webnoir.org/),这是一个新的Clojure网络应用框架(文档目前还不存在)。作为一个Django/Rails用户,我很喜欢它简单,直接的语法,而且非常轻盈。


Webnoir实际上非常有用!它非常容易上手 - 你可以像开发php一样开发它 - 只需启动服务器(这次使用leiningen),编辑您的文件并重新加载浏览器以查看您得到了什么。 - claj
由于@elithrar已经回答,Noir现在有文档可用:http://www.webnoir.org/docs/ - Alistair Collins
19
仅供参考,似乎Noir已被弃用且不再维护... - SolarBear

25

考虑使用Luminus web框架。我没有任何关联,但从我尊重的朋友那里听说了好的评价。


21

我的首选Web库现在是yada

如果你刚开始,可以使用Compojure作为入门服务器。我认为它在Clojure世界中就像是Web服务器的Apache(那么yada / aleph将是nginx)。你可以使用Luminus作为模板。还有它的变种,比如compojure-api

我尝试了Pedestal,并对它感到非常满意。我不敢说我掌握了它,但它的语法很舒适,感觉非常协调,并且看起来确实具有出色的性能。它也由Cognitect支持(Rich Hickey工作的Clojure / Datomic公司)。

我发现Aleph提供了一个有趣的抽象概念,并且内置的背压机制似乎非常有趣。我还没有试过它,但它肯定在我的列表上。

尝试了各种Web服务器后,这是我的快速优缺点列表:

简短地说:快速入门可以看看Luminus,随着需求的变化可以转向其他东西(也许是Yada)。

Compojure

  • 利:

    • 易于使用,有许多模板 / 示例(例如Luminous)
  • 弊:

    • 性能不佳(每个请求一个线程),预计表现略好于rails
    • 不简单,中间件模型有不便之处
    • Pedestal

      • 优点(3):

        • 拦截器模型,使用令人愉悦的语法向某些路由添加拦截器
        • 高效路由器
        • 支持json/transit/multipart forms文件,无需任何请求即可透明处理。非常酷!
      • 缺点(4):

        • 暂不支持websocket,返回core.async通道会很好
        • 如果将其放入Stuart Sierra组件中,重新加载有点慢(我认为你应该使用reload拦截器)
        • 没有异步拦截器的测试设施
        • 需要购买(?)

      Aleph

      优点(3):

      • 高效
      • 反压
      • 返回manifold流时支持Websocket/SSE

      缺点(1):

      • 底层,自己动手风格(即它只提供一种使处理程序做某事的方法。没有路由器,没有其他)。这不是缺点,只是要知道这一点。

      Yada

      优点(3):

      • 基于Aleph构建
      • 内容协商
      • swagger集成
      • bidi还可以(虽然我更喜欢pedestal路由器语法)

      缺点(1):

      • 文档(虽然不像nginx-clojure那么糟糕,但迅速提高)。

      HttpKit

      优点(2):

      • 用Clojure编写!(和Java ...)
      • 性能看起来不错(请参阅600K并发连接帖子)

      缺点(2):

      • 没有CORS支持
    • 存在Bug?同时,最近的提交并不多。

    Nginx-Clojure

    注:我没有尝试过它,主要是因为缺少文档。但它看起来非常有趣,而且性能很好。

    优点(2):

    • Nginx(高性能,卸载SSL,重启工作进程...)
    • 这个模型是否可以实现零停机更新?那将是非常棒的!

    缺点(1):

    • 文档需要改进。此外,如果这是唯一的方法,我不想在嵌入在Nginx配置文件中的字符串中编程。
    • 可能会使第一次部署有点复杂(?)

    Immutant

    注:我没有尝试过它。

    优点:

    • 集成(缓存、消息、调度、wildfly 部署)

    缺点:

    • 没有http客户端

    Catacumba

    注:我没有尝试过它,尽管文档看起来很好。我可能会尝试下一个。有一些有趣的示例聊天项目,它们对协议的大量使用起初让我作为一个新手Clojure开发者望而却步。

    优点(6):

    • 文档!像所有的funcool项目一样,文档非常容易阅读。
    • 类似Pedestal的路由语法
    • 应该是高性能的(基于Ratpack)
    • 反向压力
    • websockets、sse、cors、security、ssl......
    • 挖掘独特的功能:postal

    缺点(2):

    • 不完全确定ct/routes语法是否令人愉快,并且是否放弃了Ring spec(据说是为了异步故事,但我认为 pedestal 的团队已经解决了这个问题)
    • 不确定如何集成swagger等。
    • 当我尝试过它时,我无法立即使其正常工作。

    注意: 如果只关注原始性能,可用Clojure Web服务器基准测试结果


很好的比较。不过我不确定nginx的隐喻是如何起作用的 :) - matanster
1
@matanster 我看到很多组织都将Apache作为默认服务器。它简单易用,适用于许多场景。但是它比Nginx更老,并使用不同的内部模型。Compojure是同步的(可能会改变),而Yada是异步的。我没有提到的Yada的另一个好处是,一切都是数据,因此与Compojure中的宏相比,更容易组合/转换/检查/生成。 - nha

14

现在值得一看的框架之一是Pedestal。它是一个建立在Ring之上的服务端框架,但也能通过暂停和恢复特定的请求来解放入站请求的初始线程(否则一个慢请求会阻塞服务器线程),可能有点像JavaBean。

其他很酷的框架包括 hoplon.io 和 David Nolen's 基于React的Om


11

Webjure 是一个针对Clojure的web编程框架。

特点:将servlet调用指向Clojure函数。 动态生成HTML。 SQL查询接口(通过JDBC实现)。

此答案旨在为 Webjure 提供信息的占位符。


3
我不确定这个例子是否恰当。虽然代码库看起来很浅显易懂(好的),但是有足够多的Java代码,似乎没有达到预期的纯Clojure框架。 - Richard

8

我使用Compojure构建了一个小型博客应用程序。它的模型基于Sinatra,这是一个轻量级的Ruby Web框架。我主要使用了路由功能,这与Sinatra非常相似。代码如下:

(GET "/post/:id/:slug"
  (some-function-that-returns-html :id :slug))

虽然没有ORM或模板库,但它确实有将向量转换为HTML的函数。


5

1
Twister是用Go语言编写的,而不是Clojure。 - hipertracker

3

免责声明:我是作者。

我制作了一个leiningen模板,结合了luminusweb和chestnut模板。 这样你就可以构建clojure代码和前后端的clojurescript代码。
此外,它还提供了用户管理以及一些简单的CRUD生成和更多小的实用功能:https://github.com/sveri/closp


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