我是Clojure的新手,并且一直在使用Compojure编写基本的Web应用程序.不过,我正在用Compojure的defroutes语法碰壁,我认为我需要理解它背后的"如何"和"为什么".
看起来像Ring样式的应用程序以HTTP请求映射开始,然后只是通过一系列中间件函数传递请求,直到它被转换为响应映射,然后将其发送回浏览器.对于开发人员来说,这种风格似乎太"低级",因此需要像Compojure这样的工具.我可以看到在其他软件生态系统中需要更多的抽象,尤其是Python的WSGI.
问题是我不了解Compojure的方法.我们采用以下defroutesS表达式:
(defroutes main-routes
(GET "/" [] (workbench))
(POST "/save" {form-params :form-params} (str form-params))
(GET "/test" [& more] (str "<pre>" more "</pre>"))
(GET ["/:filename" :filename #".*"] [filename]
(response/file-response filename {:root "./static"}))
(ANY "*" [] "<h1>Page not found.</h1>"))
Run Code Online (Sandbox Code Playgroud)
我知道理解所有这些的关键在于一些宏观伏都教,但我还没有完全理解宏(还).我已经盯着defroutes源头很长一段时间了,但就是不明白!这里发生了什么?理解"大创意"可能会帮助我回答这些具体问题:
workbench功能)中访问Ring环境?例如,假设我想访问HTTP_ACCEPT标头或请求/中间件的其他部分?{form-params :form-params})?在解构时我可以使用哪些关键字?我真的很喜欢Clojure,但我很难过!
注意
鉴于此OP大约两年前编写,而不是再次提出相同的问题,我想知道是否存在分步说明,以便我可以将Noir或其他Clojure Web应用程序集成到Apache中,无论是Jetty,Tomcat , 或者是其他东西.Django也存在类似的指令,我想我明白Python在Django的情况下是作为引擎而不是环形框架运行的,所以Clojure Web应用程序更复杂.
结束注释
我深深爱上了Clojure,而Compojure似乎是一个整洁的Web框架.
但是当我想将我的应用程序部署在像Tomcat这样的常规应用程序服务器上作为WAR时,它就崩溃了.我实际上必须为静态文件和资源编写自定义Ring处理程序,这些文件和资源可以在本地Jetty和Tomcat上运行,因为库存处理程序没有,我不得不手动将上下文根添加到任何地方.
令我感到非常惊讶的是,我必须编写所有这些代码来创建可以在Jetty和Tomcat上运行的最简单的Web应用程序.我只有三种可能的解释:
您认为以下哪一种情况?或者是别的什么?
编辑:
请注意,创建一个战争文件是Maven/Leiningen的明智之举,而不是我的意思.我想知道我必须编写如此多的代码来使Compojure与Tomcat一起工作,基本的东西,如静态文件服务和上下文根知识应该开箱即用.
我目前正在使用Compojure(以及Ring和相关的中间件)在Clojure中编写API.
我正在尝试根据路由应用不同的身份验证代码.请考虑以下代码:
(defroutes public-routes
(GET "/public-endpoint" [] ("PUBLIC ENDPOINT")))
(defroutes user-routes
(GET "/user-endpoint1" [] ("USER ENDPOINT 1"))
(GET "/user-endpoint2" [] ("USER ENDPOINT 1")))
(defroutes admin-routes
(GET "/admin-endpoint" [] ("ADMIN ENDPOINT")))
(def app
(handler/api
(routes
public-routes
(-> user-routes
(wrap-basic-authentication user-auth?)))))
(-> admin-routes
(wrap-basic-authentication admin-auth?)))))
Run Code Online (Sandbox Code Playgroud)
这不能按预期工作,因为它wrap-basic-authentication实际上包装了路由,因此无论包装路由如何都会尝试它.具体来说,如果需要将请求路由到admin-routes,user-auth?仍将尝试(并失败).
我使出context到根在一个共同的基本路径部分航线,但它是一个相当的限制(下面的代码可能无法正常工作,它只是说明的想法):
(defroutes user-routes
(GET "-endpoint1" [] ("USER ENDPOINT 1"))
(GET "-endpoint2" [] ("USER ENDPOINT 1")))
(defroutes admin-routes
(GET "-endpoint" [] ("ADMIN ENDPOINT")))
(def app
(handler/api
(routes …Run Code Online (Sandbox Code Playgroud) 我之前在Clojure中编写了一个小型Swing应用程序,现在我想创建一个Ajax风格的Web应用程序.Compojure现在看起来是最好的选择,所以这就是我要尝试的.
我想要一个真正的小编辑/尝试反馈循环,所以我不希望在每次小改变后重启web服务器.
实现这一目标的最佳方法是什么?默认情况下,我的Compojure设置(使用带有Jetty的ant deps/ant的标准内容)似乎没有重新加载我所做的任何更改.我将不得不重新启动run-server来查看更改.由于Java遗产和系统启动的方式等.这可能是完全正常的,当我从命令行启动系统时应该是这样.
但是,必须有一种方法可以在服务器运行时动态地重新加载内容.我应该使用REPL的Compojure来实现我的目标吗?如果我应该,我怎么重新加载我的东西?
我有一个静态文件index.html,我想在有人请求时提供服务/.通常,Web服务器默认执行此操作,但Compojure不这样做.index.html当有人请求时,我如何让Compojure服务/?
这是我用于静态目录的代码:
; match anything in the static dir at resources/public
(route/resources "/")
Run Code Online (Sandbox Code Playgroud) 我正在试图找出如何创建一个具有多语言支持的基于Compojure的网站.有没有像i18n这样的解决方案?
我已经在twitter和#clojure IRC频道上提出了这个问题,但没有得到任何答复.
有几篇关于Clojure-for-Ruby程序员,Clojure-for-lisp程序员的文章......但缺少的部分是Clojure for ActiveRecord程序员.
有关于与MongoDB,Redis等进行交互的文章 - 但这些都是一天结束时的关键价值商店.但是,来自Rails背景,我们习惯于在继承方面考虑数据库 - has_many,polymorphic,belongs_to等.
关于Clojure/Compojure + MySQL(ffclassic)的几篇文章- 深入研究sql.当然,ORM可能导致阻抗不匹配,但事实仍然是,在像ActiveRecord一样思考之后,很难以其他方式思考.
我相信关系数据库非常适合面向对象的范例,因为它们本质上就是集合.像activerecord这样的东西非常适合建模这些数据.对于例如博客 - 简单地说
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
Run Code Online (Sandbox Code Playgroud)
如何在Clojure中对此进行建模 - 这是如此严格的反OO?如果提到所有函数式编程语言,问题可能会更好,但我更感兴趣的是Clojure的观点(以及Clojure示例)
我最近开始探索Clojure,我想建立一个具有基本CRUD功能的简单Web应用程序.我在这里找到了一个很好的教程:http://www.xuan-wu.com/2013-09-21-Basic-Web-Application-in-Clojure.
GET请求工作正常,但每当我尝试发布请求时,都会收到以下错误:
Invalid anti-forgery token
Run Code Online (Sandbox Code Playgroud)
我之前提到的教程没有涉及任何安全相关的问题.我做了一些挖掘,似乎我错过了Compojure的一些组件,它应该生成一个用于发出POST请求的令牌.有些地方提到我应该自动发生,而我没有任何改变.我仍然不确定我失踪了什么.这是我的代码:
(ns myblog.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[myblog.views :as views]
[myblog.posts :as posts]
[ring.util.response :as resp]
[ring.middleware.basic-authentication :refer :all]))
(defn authenticated? [name pass]
(and (= name "user")
(= pass "pass")))
(defroutes public-routes
(GET "/" [] (views/main-page))
(route/resources "/"))
(defroutes protected-routes
(GET "/admin" [] (views/admin-page))
(GET "/admin/add" [] (views/add-post))
(POST "/admin/create" [& params]
(do (posts/create params)
(resp/redirect "/admin"))))
(defroutes app-routes
public-routes
(wrap-basic-authentication protected-routes authenticated?)
(route/not-found …Run Code Online (Sandbox Code Playgroud) 我无法理解clojure的Noir库.它似乎是一个在compojure之上编写的框架,它将defroute重命名为defpage并将其称为一天.显然是一种不公平的简化,但Noir到底带来了什么呢?为什么我会使用Noir而不是简单的组合+打嗝?
编辑/更新:Noir已被弃用,有趣的是在这里写:http://blog.raynes.me/blog/2012/12/13/moving-away-from-noir/.
我正在使用Maven作为我的依赖管理器在IntelliJ中使用基于Compojure的Clojure Web应用程序.它基于我在此示例引用的此git存储库中找到的应用程序.当我尝试使用IntelliJ的Tomcat6配置运行应用程序时,每次引用Servlet异常时都会失败:
javax.servlet.ServletException: Wrapper cannot find servlet class tracker.core or a class it depends on
Run Code Online (Sandbox Code Playgroud)
另外,查看web.xml,IntelliJ无法识别servlet类(tracker.core突出显示).
这个应用程序最初是作为客户的概念证明而构建的,由我最近离开公司的同事编写.在过去的两天里,除了在这个项目上工作之外,我个人对clojure没有任何经验.使用Leiningen环服务器,我可以成功地让应用程序在jetty中运行.使用leiningen ring uberwar,由此产生的战争成功地部署并运行在tomcat中.
原始文件结构如下所示:
/tracker-webapp
/classes
/lib
/resources
/src
/tracker
/core.clj (and other *.clj files)
/test
project.clj
Run Code Online (Sandbox Code Playgroud)
新的mavenized文件结构现在反映了前面提到的git repo中的示例:
/tracker-webapp
/src
/main
/clojure
/tracker
/core.clj (and other *.clj files)
/webapp
/WEB-INF
/web.xml
/pom.xml
Run Code Online (Sandbox Code Playgroud)
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Simple Clojure WebApp</display-name>
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>tracker.core</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/*</url-pattern> …Run Code Online (Sandbox Code Playgroud) clojure ×10
compojure ×10
deployment ×1
maven ×1
middleware ×1
multilingual ×1
mysql ×1
noir ×1
post ×1
postgresql ×1
ring ×1
routes ×1
tomcat ×1
war ×1