问题描述
我在Clojure中写了一个小的Swing应用程序,现在我想创建一个Ajax风格的Web应用程序。 Compojure看起来像是现在最好的选择,所以这就是我要试试。
I've written a small Swing App before in Clojure and now I'd like to create an Ajax-style Web-App. Compojure looks like the best choice right now, so that's what I'm going to try out.
我想有一个真正的微小的编辑/尝试反馈循环,所以我宁愿不重新启动网络服务器,每次小改变后,我做。
I'd like to have a real tiny edit/try feedback-loop, so I'd prefer not to restart the web server after each small change I do.
最好的方法是什么?默认情况下,我的Compojure设置(标准的东西与ant deps / ant与Jetty)似乎不重新加载任何更改我做。我必须重新启动与运行服务器,以查看更改。因为Java的遗产和系统的启动方式等。这可能是完全正常的,当我从命令行启动系统时应该是这样的方式。
What's the best way to accomplish this? By default my Compojure setup (the standard stuff with ant deps/ant with Jetty) doesn't seem to reload any changes I do. I'll have to restart with run-server to see the changes. Because of the Java-heritage and the way the system is started etc. This is probably perfectly normal and the way it should be when I start the system from command-line.
仍然,在服务器运行时,必须有一种方法来动态重新载入内容。我应该使用Compojure从REPL来完成我的目标吗?如果我应该,如何重新加载我的东西在那里?
Still, there must be a way to reload stuff dynamically while the server is running. Should I use Compojure from REPL to accomplish my goal? If I should, how do I reload my stuff there?
推荐答案
这是一个相当古老的问题,最近有一些变化让这更容易了。
This is quite an old question, and there have been some recent changes that make this much easier.
您需要两个主要的东西:
There are two main things that you want:
- 控制应该返回REPL,继续与您的服务器交互。这是通过添加{:join?
- 当文件更改时,您希望自动选择某些命名空间中的更改。这可以通过Ring的wrap-reload中间件完成。
玩具应用程序如下所示:
A toy application would look like this:
(ns demo.core
(:use webui.nav
[clojure.java.io]
[compojure core response]
[ring.adapter.jetty :only [run-jetty]]
[ring.util.response]
[ring.middleware file file-info stacktrace reload])
(:require [compojure.route :as route] view)
(:gen-class))
; Some stuff using Fleet omitted.
(defroutes main-routes
(GET "/" [] (view/layout {:body (index-page)})
(route/not-found (file "public/404.html"))
)
(defn app
[]
(-> main-routes
(wrap-reload '(demo.core view))
(wrap-file "public")
(wrap-file-info)
(wrap-stacktrace)))
(defn start-server
[]
(run-jetty (app) {:port 8080 :join? false}))
(defn -main [& args]
(start-server))
wrap-reload函数(我的视图命名空间是由Fleet动态创建的,所以这会自动重载我的模板任何时候,我们可以使用这个函数来处理请求,如果这些命名空间在磁盘上发生了变化,他们也改变了。)
The wrap-reload function decorates your app routes with a function that detects changes in the listed namespaces. When processing a request, if those namespaces have changed on disk, they are reloaded before further request processing. (My "view" namespace is dynamically created by Fleet, so this auto-reloads my templates whenever they change, too.)
我添加了一些其他的中间件,我发现一贯有用。wrap-file处理静态资源。 wrap-file-info在这些静态资产上设置MIME类型。 wrap-stacktrace帮助调试。
I added a few other pieces of middleware that I've found consistently useful. wrap-file handles static assets. wrap-file-info sets the MIME type on those static assets. wrap-stacktrace helps in debugging.
从REPL,你可以使用命名空间和直接调用start-server启动这个应用程序。 :gen-class关键字和-main函数意味着该应用程序也可以打包为一个uberjar从启动REPL外。 (在REPL之外有一个世界?好了,有些人已经要求了...)
From the REPL, you could start this app by using the namespace and calling start-server directly. The :gen-class keyword and -main function mean that the app can also be packaged as an uberjar for startup from outside the REPL, too. (There's a world outside the REPL? Well, some people have asked for it anyway...)
这篇关于无需重新启动Web服务器的Compojure开发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!