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