Keep it simple stupid
用慣了Rails了之后,你發現你可以很快的解決一個問題,知道用什么Gem去解決相應的問題,但是你很少會去關注在這之后到底發生了什么。因為一切都在一個大盒子里面,拿來就可以用。
所以我要分享一些簡單基礎的東西,比如寫一個中間件。
Demon‘s run
lein new compojure run
這個命令會新建一個空空的工程。
lein ring server-headless & curl localhost:3000
# => Hello World
就可以跑起來了。
接下來添加一些奇奇怪怪的clojars,編輯你的project.clj和handler.clj文件
; project.clj
(defproject run "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.8.0"]
[compojure "1.5.1"]
[ring/ring-defaults "0.2.1"]
[ring-logger-timbre "0.7.5"]
[ring/ring-json "0.4.0"]
[korma "0.4.3"]]
:plugins [[lein-ring "0.9.7"]]
:ring {:handler run.handler/app}
:profiles
{:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
[ring/ring-mock "0.3.0"]]}})
; handler.clj
(ns run.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults api-defaults]]
[ring.logger.timbre :as logger.timbre]
[ring.util.response :refer [response]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]))
(defroutes app-routes
(GET "/" [] (response {:msg "hello rworld"}))
(route/not-found "Not Found"))
(defn test-middleware [handler]
(fn [request]
(handler request)))
(def app
(-> app-routes
(wrap-defaults api-defaults)
test-middleware
logger.timbre/wrap-with-logger
wrap-json-response
wrap-json-body))
針對上面的我說一些簡單東西:
1、上面的test middleware就是一個最簡單的middleware,可以在fn中寫任何你想要的代碼,比如(print ":)")
,默認的app那部分其實之前不是這么寫的,我用->
這個宏來改寫一下閱讀的順序,所以就會出現
(-> app-routes
(wrap-defaults api-defaults)
test-middleware ;這是我們自己寫的middleware
logger.timbre/wrap-with-logger ;這個是timbre這個log庫
wrap-json-response ;??這兩個是用來處理json的輸入輸出的
wrap-json-body)
其中json相關的功能由ring-json提供。
很重要的就是處理順序是test-middleware -> logger.timbre/wrap-with-logger -> wrap-json-response -> wrap-json-body 然后再到api endpoint的。
關于->
這個還有->>
這個宏在多說一些
;; Use of `->` (the "thread-first" macro) can help make code
;; more readable by removing nesting. It can be especially
;; useful when using host methods:
;; Arguably a bit cumbersome to read:
user=> (first (.split (.replace (.toUpperCase "a b c d") "A" "X") " "))
"X"
;; Perhaps easier to read:
user=> (-> "a b c d"
.toUpperCase
(.replace "A" "X")
(.split " ")
first)
;; An example of using the "thread-last" macro to get
;; the sum of the first 10 even squares.
user=> (->> (range)
(map #(* % %))
(filter even?)
(take 10)
(reduce +))
1140
;; This expands to:
user=> (reduce +
(take 10
(filter even?
(map #(* % %)
(range)))))
1140
(-> 3 (- 2)) ; It means (- 3 2)
=> 1
(->> 3 (- 2)) ; It means (- 2 3)
=> -1