【问题标题】:Dynamic handler update in Clojure Ring/Compojure REPLClojure Ring/Compojure REPL 中的动态处理程序更新
【发布时间】:2015-05-08 09:08:54
【问题描述】:

我使用lein new compojure test 创建了一个新的 Compojure Leiningen 项目。 Web服务器由lein repl运行,然后

user=> (use 'ring.adapter.jetty)
user=> (run-jetty test.handler/app {:port 3000})

路由和应用处理程序规范很简单:

(defroutes app-routes
  (GET "/*.do" [] "Dynamic page")
  (route/not-found "Not Found"))

(def app
  (wrap-defaults app-routes site-defaults))

现在,在更改 app-routes 定义中的任何内容(例如,将“动态页面”文本更改为其他任何内容,或修改 URI 匹配字符串)后,我没有在浏览器中获得更新的文本/路由。但是,将app-routes 定义稍微更改为

(defn dynfn [] "Dynamic page fn")
(defroutes app-routes
  (GET "/*.do" [] (dynfn))
  (route/not-found "Not Found"))

在更改dynfn 的返回值时,我确实获得了动态更新。另外,遵循this article 的建议并将app 定义修改为

(def app
  (wrap-defaults #'app-routes site-defaults))

(注意#' 透明地为app-routes 创建一个变量)也有帮助!

为什么会这样?有没有其他方法可以在defroutes 中获得真正的动态行为?

谢谢!

【问题讨论】:

    标签: clojure read-eval-print-loop ring compojure


    【解决方案1】:

    #'app-routes 是一个扩展为(var app-routes) 的阅读器宏。当一个 var 像一个函数一样被使用时,它会在每次调用时重新取消引用,然后调用该 deref 返回的值。

    如果您要提供app-routes 作为参数,编译器会将取消引用的值赋予wrap-defaults,并且当更新 var 时,之前的值不会改变,因此更改 var 不会改变行为app.

    以下 repl 记录可能具有指导意义:

    user=> (defn foo [] "original")
    #'user/foo
    user=> (defn caller [f] #(f))
    #'user/caller
    user=> (def call-foo-value (caller foo))
    #'user/call-foo-value
    user=> (call-foo-value)
    "original"
    user=> (def call-foo-var (caller #'foo))
    #'user/call-foo-var
    user=> (call-foo-var)
    "original"
    user=> (defn foo [] "changed")
    #'user/foo
    user=> (call-foo-value)
    "original"
    user=> (call-foo-var)
    "changed"
    

    【讨论】:

    • 感谢完美的解释。我实际上希望它包含在更多的 Ring/Compojure 教程中。非常感谢!
    猜你喜欢
    • 2015-03-15
    • 2011-05-26
    • 2012-11-19
    • 2015-04-16
    • 2013-12-04
    • 2014-11-25
    • 2014-07-21
    • 2013-04-29
    • 2013-06-06
    相关资源
    最近更新 更多