Ring 的目标是把 HTTP 的细节抽象为简单且模块化的 API,它与 Python 的 WSGI 和 Ruby 的 Rake 非常类似。可以用来构建类型广泛的应用。
新建基于 default 模板的项目:
$ lein new hello
修改 hello/project.clj 文件,添加依赖和入口配置,如下:
(defproject hello "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[ring/ring-devel "1.4.0"]
[ring/ring-core "1.4.0"]
[http-kit "2.1.19"]]
:main hello.core/-main)
执行 lein deps 下载依赖。
开发服务器采用 http-kit ,这是一个异步高性能 web 服务器,志在取缔 jetty。我们需要向 http-kit 注册一个 handler。当我们请求 http-kit 服务器时,http-kit 会调用事先注册好的 handler 。handler 必须返回一个 response map。格式如下:
{:status 200
:header {"Content-Type" "text/html"}
:body "hello world"}
其中 :status 为状态码,:header 为响应头部,:body 为响应数据。
http-kit 提供了极为简单易用的函数调用来启动一个服务:
(run-server handler & [request-map])
一个简单的例子:
(ns hello.core
(:use [org.httpkit.server :only [run-server]]))
(defn handler [request]
{:status 200
:header {"Content-Type" "text/html"}
:body "hello world\n"})
(defn -main [& args]
(run-server handler {:port 5000})
(println "Start Http-Kit Server On Port 5000..."))
在命令行执行:
$ lein run
Start Http-Kit Server On Port 5000...
访问:
$ curl http://localhost:5000
hello world
http-kit 的 run-server 方法接受2个参数。第一个参数是注册的 handler,并且这个 handler 必须是一元参数函数(参数为请求对象),第二个参数为选项,用于对 http-kit 进行设置。解释如下:
Options:
:ip ; 指定监听的IP地址(默认为:0.0.0.0)
:port ; 指定监听的端口(默认为:8090)
:thread ; HTTP工作线程数量(默认为:4)
:queue-size ; 最大队列大小(默认为:20KB)
:max-body ; 最大HTTP包体大小(默认为:8MB)
:max-ws ; 最大websocket消息大小(默认为:4MB)
:max-line ; HTTP url的最大长度(默认为:4KB)
:proxy-protocol ; 禁用或启用代理协议(默认为::disable)
:worker-name-prefix ; 工作线程名称前缀(默认为:worker-)
Ring 还自带了 reponse 来进行响应,避免我们手工构造 response map。修改 handler 代码,如下:
(ns hello.core
(:use [org.httpkit.server :only [run-server]]
[ring.util.response :only [response]]))
(defn handler [request]
(response "hello world\n"))
(defn -main [& args]
(run-server handler {:port 5000})
(println "Start Http-Kit Server On Port 5000..."))
Ring 是基础构件,http-kit 自始至终只是调用 handler。我们来尝试几次请求:
$ curl http://localhost:5000
hello world
$ curl http://localhost:5000/a/b/c
hello world
聪明的你一定想得到,如果在 handler 里进行路由分发会怎么样呢?compojure 就是来干这个事的。本文只是稍稍带大家领略 Clojure 的 web 开发之美,下次再给大家带来 Ring 中间件和 compojure 的路由处理,希望大家能喜欢!