DEV Community

kaede
kaede

Posted on

Clojure Tutorial Part 6 -- サーバーファイルのメソッドからサーバーの起動、停止、再起動をできるようになる

参考

https://scrapbox.io/ayato-p/Part1_Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%E3%81%98%E3%82%81%E3%81%AE%E4%B8%80%E6%AD%A9

引き続き、ayato-p さんの記事の

新しいネームスペースを作って保存する

の章を参考にする。

 (ns cljblog.server
   (:require [ring.adapter.jetty :as jetty]))

 (defonce server (atom nil))

 (defn handler [req]
   {:status 200
    :headers {"Content-Type" "text/plain"}
    :body "Hello, world!"})

 (defn start []
   (when-not @server
     (let [options {:port 3000 :join? false}]
       (reset! server (jetty/run-jetty handler options)))))

 (defn stop []
   (when @server
     (.stop @server)
     (reset! server nil)))

 (defn restart []
   (stop)
   (start))
Enter fullscreen mode Exit fullscreen mode

main として読み込まれる src/cljblog/core.clj に並列して
src/cljblog/ に server.clj を作成する。

詳しくみていくと

 (ns cljblog.server
   (:require [ring.adapter.jetty :as jetty]))

 (defonce server (atom nil))
Enter fullscreen mode Exit fullscreen mode

ns でファイル名を明記

defonce と atom はサーバー変数を起動、停止、再起動で使うためにあるらしい。

 (defn handler [req]
   {:status 200
    :headers {"Content-Type" "text/plain"}
    :body "Hello, world!"})
Enter fullscreen mode Exit fullscreen mode

最初に共通処理として handler 関数を作る。
全てのリクエストで

  • status 200
  • contentType プレーンテキスト
  • body "Hello, World!"

これらを渡すようにする。

 (defn start []
   (when-not @server
     (let [options {:port 3000 :join? false}]
       (reset! server (jetty/run-jetty handler options)))))
Enter fullscreen mode Exit fullscreen mode

start では server 変数が無い時にのみ動いて
options に port と join を追加して

server に jetty を handler と options の値を渡す。
するとサーバーが起動される。

https://clojuredocs.org/clojure.core/reset!

reset! は引数の値を書き換えるためのメソッド。

 (defn stop []
   (when @server
     (.stop @server)
     (reset! server nil)))
Enter fullscreen mode Exit fullscreen mode

stop では server 変数の中身がある時に .stop を与えて
reset! で server 変数を空にする。

 (defn restart []
   (stop)
   (start))
Enter fullscreen mode Exit fullscreen mode

restart は単に stop の後に start を実行している。

実際に動かす

lein repl
cljblog.core=> 
Enter fullscreen mode Exit fullscreen mode

lein repl で起動して

(require '[cljblog.server :as server])

2022-06-05 22:40:17.170:INFO::nREPL-session-1dd10f13-948c-4f56-ba35-317335f370eb: Logging initialized @42123ms to org.eclipse.jetty.util.log.StdErrLog
nil
Enter fullscreen mode Exit fullscreen mode

さっき作った server ファイルを import

(server/start)
Started @77584ms
Enter fullscreen mode Exit fullscreen mode

Image description

その start を呼ぶとサーバーが動く

Stopped ServerConnector@5a2fa9ff{HTTP/1.1,[http/1.1]}{0.0.0.0:3000}
Enter fullscreen mode Exit fullscreen mode

stop も

 (server/restart)
Started ServerConnector@6e0dc191{HTTP/1.1,[http/1.1]}{0.0.0.0:3000}

(server/restart)
Stopped ServerConnector@6e0dc191{HTTP/1.1,[http/1.1]}{0.0.0.0:3000}
Started ServerConnector@9da958b{HTTP/1.1,[http/1.1]}{0.0.0.0:3000}
Enter fullscreen mode Exit fullscreen mode

restart も起動した。


まとめ

Clojure でサーバーの操作コマンドを作るためには

server ファイルを作成し、

共通の handler 関数を作り
status, headers, body,
これらを渡すようにする

start 関数では
server 変数の中身がない場合のみ動いて
options の port, join を渡して
server 変数に run-jetty と
さっき作った options と共通関数の handler
これらを渡す。

stop 関数は逆で
server 変数がある時のみ動いて
.stop を server にぶち込んで
server 変数に nil (null 相当)をぶち込みます

restart は stop と start

そして、repl を起動して import してこれらを呼ぶ。
以上。

Top comments (0)