Compojure/教程和技巧
| 此頁面可能需要更新以反映當前知識。 您可以 幫助更新它,討論進度,或 請求幫助。 |
這是一個使用 Compojure Web 框架的示例集合。
Compojure 預設情況下不提供靜態檔案,也不會在沒有匹配路由時自動處理 404 錯誤。Compojure 不會對你想做什麼做任何假設;你必須明確說明。
為了提供靜態檔案,你通常需要新增兩個處理程式。一個用於服務檔案,另一個用於在第一個處理程式失敗時引發 404 錯誤
(compojure.route/files "public") (compojure.route/not-found "Not found.")
如 https://weavejester.github.io/compojure/compojure.route.html 文件所述
使用名稱空間和 :require 對映,例如
(ns coolproject.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]))
然後你對 compojure.route 的呼叫可以簡化為
(route/files "public")
它將自動在你的 src/resources/public 目錄中查詢靜態檔案(.css、影像等)。
兩個 Compojure Servlet 相比一個 Servlet 的唯一優勢是功能劃分清晰。例如,如果你的網站有一個與公共網站截然不同的管理員介面,你可能希望建立兩個 Servlet;一個用於公共訪問,另一個用於管理員控制面板。
另一種需要多個 Servlet 的情況是,你的一個 Servlet 是用 Java 編寫的。例如,Jetty 包含一個用於處理 Cometd 請求的 Servlet,ContinuationCometdServlet。在我使用 Compojure 構建的應用程式中,我將此 Servlet 繫結到 "/_cometd/*",並將我的主要 Compojure Servlet 繫結到 "/*".
但對於正常使用,我傾向於將所有內容都放在一個 Servlet 中。如果你看一下像 Ruby on Rails 這樣的框架,所有的路由資訊都儲存在一個檔案中。Compojure Servlet 具有類似的用途,它們充當通往構成你的網站的 Clojure 函式的閘道器。實際的 Servlet 本身應該包含很少的邏輯,它應該看起來幾乎像整個網站的高階概述。
以下程式碼定義了 input-date-field 函式,它可以像其他任何輸入輔助函式一樣使用。該表單將以 Unix 時間格式返回日期。引數是:表單欄位的名稱、當前值以及年份選擇器的起始年和結束年。
;;; Date form field
(def *date-class* (.getClass (new java.util.Date (long 0))))
(def *date-format* (new java.text.SimpleDateFormat "yyyy-MM-dd"))
(defn parseLong [s]
(try (Long/parseLong (str s)) (catch java.lang.Exception e 0)))
(defn get-date-from-anything [value]
"Returns a Date object. Accepts a Date, number or String."
(cond
(nil? value)
(new java.util.Date (long 0))
(instance? *date-class* value)
value
(number? value)
(new java.util.Date (* 1000 (long value)))
true
(new java.util.Date (* 1000 (long (parseLong (str value)))))))
(import '(java.util Calendar))
(def monthNames ["January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December"])
(defn input-date-field
"Creates a form element to input a date"
[name value fromYear toYear]
(let [calendar (Calendar/getInstance)
name (.replaceAll (str name) ":" "")]
(.setTime calendar (get-date-from-anything value))
(html
(str "<script>
function changed_date_" name "()
{
function $(id) { return document.getElementById(id); }
var date = new Date(parseInt($('year_" name "').value), parseInt($('month_" name "').value), parseInt($('day_" name "').value));
$('" name "').value = date.getTime() / 1000;
//alert('c=:' + $('" name "').value);
}
</script>")
[:input {:type 'hidden :name name :id name :value value}]
[:input {:type 'text :id (str "day_" name) :value (.get calendar Calendar/DAY_OF_MONTH) :size 1 :onchange (str "changed_date_" name "();")}] " "
[:select {:id (str "month_" name) :onchange (str "changed_date_" name "();")}
(reduce #(str % (html [:option {:value %2 :selected (if (= %2 (.get calendar Calendar/MONTH)) "true" nil)} (nth monthNames %2)])) "" (range 12))] " "
[:select {:id (str "year_" name) :onchange (str "changed_date_" name "();")}
(reduce #(str % (html [:option {:value (+ fromYear %2)} (+ fromYear %2)])) "" (range (- (inc toYear) fromYear)))] " "
)))