lein ring server 浅谈

在lepl中 “lein ring server”,启动ring 服务,下面浅谈其调用过程。

lein ring server是个lein 插件调用(lein.ring) 而后根据参数server 调用->(leiningen.ring.server) 这个方式之前的文章也讲过。

(defn load-namespaces
  "Create require forms for each of the supplied symbols. This exists because
  Clojure cannot load and use a new namespace in the same eval form."
  [& syms]
    ~@(for [s syms :when s]
        `'~(if-let [ns (namespace s)]
             (symbol ns)
(defn start-server-expr [project]
  `(ring.server.leiningen/serve '~(select-keys project [:ring])))
(defn server-task
  "Shared logic for server and server-headless tasks."
  [project options]
  (ensure-handler-set! project)
  (let [project (-> project
                    (assoc-in [:ring :reload-paths] (reload-paths project))
                    (update-in [:ring] merge options))]
     (-> project add-server-dep add-optional-nrepl-dep)
     (if (nrepl? project)
       `(do ~(start-nrepl-expr project) ~(start-server-expr project))
       (start-server-expr project))
     (apply load-namespaces
            (conj (into
                    (if (nrepl? project) 'clojure.tools.nrepl.server)]
                   (if (nrepl? project) (nrepl-middleware project)))
                  (-> project :ring :handler)
                  (-> project :ring :init)
                  (-> project :ring :destroy))))))

(defn server
  "Start a Ring server and open a browser."
     (server-task project {}))
  ([project port]
     (server-task project {:port (Integer. port)})))

从(leiningen.ring.server) 的server方法开始说起
前面提取project.clj :ring 值(包含handler xxx)
之后nrepl? 判读存在 :nrepl 值 即是否自定义端口(:nrepl – A map of :start? and (optionally) :port keys. If :start? is true, open up an nREPL server on the given port. :start? defaults to false, :port defaults to an arbitrary free port.),这个无关痛痒。

(start-server-expr project) 将ring的启动代码加入,不是执行。其中ring.server.leiningen/serve 是ring启动的句柄,放到下一篇《ring 启动》再说
然后load-namespaces 加载所需的ns 同样返回的是symbol

最后使用eval-in-project(用的是leinjacker) 其函数定义如下:

(defn eval-in-project
  "Support eval-in-project for both Leiningen 1.x and 2.x.  This code is
  inspired from the code in the lein-swank plug-in."
  [project form init])

可以猜出它大致是初始化namespace,适配lein project 执行form的。

至此,整个lein 启动ring server初步流程就是这样,若要详细跟进,可以看github的源码。