37

以前に Clojure で小さな Swing アプリを作成したことがありますが、今は Ajax スタイルの Web アプリを作成したいと考えています。Compojure が今のところ最良の選択のように見えるので、それを試してみます。

本当に小さな編集/試行フィードバック ループが必要なので、小さな変更を行うたびに Web サーバーを再起動したくありません。

これを達成するための最良の方法は何ですか? デフォルトでは、私の Compojure セットアップ (ant deps/ant と Jetty の標準的なもの) は、私が行った変更をリロードしていないようです。変更を確認するには、run-server で再起動する必要があります。Java の継承とシステムの起動方法などが原因です。これはおそらく完全に正常であり、コマンドラインからシステムを起動するときの方法です。

それでも、サーバーの実行中に動的にリロードする方法が必要です。目標を達成するために、REPL の Compojure を使用する必要がありますか? 必要な場合、どうすれば自分のものをそこにリロードできますか?

4

8 に答える 8

38

これはかなり古い質問であり、これをより簡単にする最近の変更がいくつかあります。

必要なものは主に 2 つあります。

  1. サーバーとのやり取りを続けることができるように、制御は REPL に戻る必要があります。これは、{:join? false} を Jetty サーバーの起動時のオプションに追加します。
  2. ファイルが変更されたときに、特定の名前空間の変更を自動的に取得したいと考えています。これは、Ring の「wrap-reload」ミドルウェアで実行できます。

おもちゃのアプリケーションは次のようになります。

(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 によって動的に作成されるため、テンプレートが変更されるたびに自動的に再読み込みされます。)

一貫して有用であることがわかった他のいくつかのミドルウェアを追加しました。wrap-file は静的アセットを処理します。wrap-file-info は、これらの静的アセットの MIME タイプを設定します。wrap-stacktrace はデバッグに役立ちます。

REPL から、名前空間を使用して start-server を直接呼び出すことで、このアプリを開始できます。:gen-class キーワードと -main 関数は、アプリを REPL の外部から起動するための uberjar としてもパッケージ化できることを意味します。(REPL の外に世界はありますか? まあ、何人かの人々はとにかくそれを求めています...)

于 2011-01-24T04:22:43.140 に答える
22

Compojure Google Group のJames Reevesから得た回答を次に示します (回答は、彼の許可を得てここに掲載しています)。

use または require コマンドで :reload キーを使用して、Clojure で名前空間をリロードできます。たとえば、ルートを含む「demo.clj」ファイルがあるとします。

(ns demo 
  (:use compojure))

(defroutes demo-routes 
  (GET "/" 
    "Hello World") 
  (ANY "*" 
    [404 "Page not found"])) 

REPL では、このファイルを使用してサーバーを起動できます。

user=> (use 'demo) 
nil 
user=> (use 'compojure) 
nil 
user=> (run-server {:port 8080} "/*" (servlet demo-routes)) 
... 

run-server コマンドを別の clojure ファイルに入れることもできます。ただし、リロードしたいものと同じファイルに入れたくありません。

次に、demo.clj にいくつかの変更を加えます。REPL タイプで:

user=> (use 'demo :reload) 
nil 

これで、変更がhttp://localhost:8080に表示されるはずです

于 2009-11-03T11:22:11.037 に答える
14

最新の回答から状況が少し変化し、自分でこれを探すのに少し時間を費やしたので、回答を追加したかったのです。

  1. leiningenをインストールします(そこの指示に従ってください)

  2. プロジェクトを作成

    lein new compojure compojure-test 
    
  3. project.cljのリング部分を編集

    :ring {:handler compojure-test.handler/app 
           :auto-reload? true
           :auto-refresh? true}
    
  4. 任意のポートでサーバーを起動します

    lein ring server-headless 8080
    
  5. サーバーがブラウザで実行されていることを確認します。デフォルトのベース ルートは「Hello world」とだけ表示されます。次に、ハンドラーを変更します (src/project_name にあります)。hello world のテキストを変更し、ファイルを保存して、ブラウザーでページをリロードします。新しいテキストを反映する必要があります。

于 2013-01-23T04:06:03.707 に答える
5

ジム・ダウニングのセットアップへのティモシーのリンクをフォローアップし、最近、開発中にcompojureアプリの自動再デプロイを有効にするために必要であることがわかったベースラインへの重要な追加について投稿しました。

于 2010-01-08T13:39:54.420 に答える
4

次のようなシェルスクリプトがあります。

#!/bin/sh                                                                                                                                   
CLASSPATH=/home/me/install/compojure/compojure.jar
CLASSPATH=$CLASSPATH:/home/me/clojure/clojure.jar
CLASSPATH=$CLASSPATH:/home/me/clojure-contrib/clojure-contrib.jar
CLASSPATH=$CLASSPATH:/home/me/elisp/clojure/swank-clojure

for f in /home/me/install/compojure/deps/*.jar; do
    CLASSPATH=$CLASSPATH:$f
done

java -server -cp $CLASSPATH clojure.lang.Repl /home/me/code/web/web.clj

web.clj は次のようになります

(use '[swank.swank])                                                                                                                        
(swank.swank/ignore-protocol-version "2009-03-09")                                                                                          
(start-server ".slime-socket" :port 4005 :encoding "utf-8")

サーバーを更新するときはいつでも、ローカル マシンからリモート マシンへの ssh トンネルを作成します。

Enclojure と Emacs (SLIME+swank-clojure を実行) はリモート REPL に接続できます。

于 2009-11-03T15:53:05.343 に答える
3

これは構成に大きく依存しますが、私にとってはうまくいき、あなたはそれを適応させることができると思います:

  1. compojure.jarを配置すると、compojure/depsディレクトリの下のjarファイルがクラスパスにあります。私はこれを行うためにclojure-contrib/launchers / bash / clj-env-dirを使用します。あなたがする必要があるのは、CLOJURE_EXTにディレクトリを設定することだけで、jarが見つかります。CLOJURE_EXT最上位のコンテンツが(直接またはシンボリックリンクとして)jarファイルであるディレクトリおよび/またはパスがClojureのクラスパスにあるディレクトリへのパスのコロン区切りリスト。

  2. clojureREPLを起動します

  3. compojureルートディレクトリからhello.cljの例を貼り付けます

  4. localhost:8080を確認してください

  5. グリーターを再定義します(グリーターをdefroutes(GET "/"(html [:h1 "Goodbye World"])))

  6. localhost:8080を確認してください

REPLを既存のプロセスにアタッチする方法もあります。または、サーバーにソケットREPLを埋め込んだままにするか、その場で評価するPOST呼び出しを定義して、ブラウザー自体から関数を再定義することもできます。これにアプローチする方法はたくさんあります。

于 2009-11-03T11:01:13.787 に答える
0

Compojure はリングを内部的に (同じ作成者によって)使用します。リング Web サーバー オプションにより、自動再ロードが可能になります。したがって、2 つの選択肢は次のようになります。

lein ring server
lein ring server-headless
lein ring server 4000
lein ring server-headless 4000

ご了承ください :

project.clj ファイルに次のような行が必要です:
:ring {:handler your.app/handler}

于 2015-03-14T20:28:31.657 に答える