Ring — это основной инструмент для выполнения вашего кода Clojure в среде веб-сервера путем удовлетворения HTTP-запросов и получения ответов. По своему объему Ring похож на Servlet API, но он не такой стандартный и распространенный; Кстати, сервлеты всегда используются внутри реализации Clojure стека HTTP.
Существуют и другие инструменты с открытым исходным кодом для веб-разработки Clojure, которые используют Ring в качестве компонента, например Compojure. Существуют даже фреймворки с полным стеком, такие как Noir, но в этой статье мы будем придерживаться простого API-интерфейса Ring и оставим более сложные подходы на будущее. Ссылки на код, показанный в этой статье, включены в раздел Ресурсы.
Привет мир
Проекты Clojure используют Leiningen * link * для извлечения зависимостей и запуска своего кода. Leiningen — это оболочка для Ant и Maven, которая извлечет для вас JAR-файлы и выполнит набор тестов или само приложение.
В проекте с поддержкой Leiningen файл project.clj определяет зависимости:
(defproject clojure-web-hello-world-ring "1.0.0-SNAPSHOT" :description "Web application Hello World with Clojure" :dependencies [[org.clojure/clojure "1.2.1"] [ring/ring "1.0.1"]] :main clojure-web-hello-world-ring.core)
Первые две строки указывают имя, версию и описание; это нефункциональные свойства в этом примере, и вы можете поместить туда что угодно.
: Зависимости ключ определяет , что вытянется: в этом случае, проект фасада для кольца , которое будет зависеть , в свою очередь , как на производственных коды объектов , как Jetty и на разработчик инструментов.
Наконец, project.clj задает имя пространства имен , где -main функция находится: эта функция будет вызвана с LEIN перспективе .
Src / clojure-web-hello-world-ring / core.clj определяет фактический код для запуска:
(ns clojure-web-hello-world-ring.core (:use ring.adapter.jetty)) (defn app [req] {:status 200 :headers {"Content-Type" "text/html"} :body "Hello World!"}) (defn -main [] (run-jetty #'app {:port 8080}))
Зависимость, которую мы импортируем — это ring.adapter.jetty, оболочка над встроенным контейнером сервлетов Jetty, который будет запускать наш код.
Мы также определяем функцию app , которая принимает в качестве аргумента карту запроса и возвращает карту ответа. Эти два — старые структуры данных Clojure.
Функция -main запускает Jetty на порте 8080 и говорит ему обрабатывать все запросы с помощью этого простого обработчика, который просто выводит «Hello World!».
Чуть более сложный пример
Теперь, когда мы связали контейнер сервлетов с кодом Clojure, у вас есть веб-приложение, полное Turing: вы можете создать что-нибудь с этим шаблоном (хотя другие библиотеки могут сэкономить ваше время).
В качестве примера приведем более одного вида запроса:
(ns clojure-web-hello-world-ring.core (:use ring.adapter.jetty) (:use clojure.string)) (defn extract-name [uri] (replace-first uri "/" "")) (defn app [req] {:status 200 :headers {"Content-Type" "text/html"} :body (if (= (:uri req) "/") "Hello, World!" (str "Hello, " (extract-name (:uri req)) "!"))}) (defn -main [] (run-jetty #'app {:port 8080}))
Теперь http: // localhost: 8080 покажет «Привет, мир!». http: // localhost: 8080 / giorgio (или любое другое имя) будет отображать «Hello, giorgio!» вместо.
Другие ресурсы
Пример кода для этой статьи на Github ; если вы вернетесь на одну ревизию в истории, вы также найдете первый пример Hello World. Чтобы запустить код, не забудьте запустить lein deps и lein run после клонирования.
Кольцо содержит небольшую спецификацию, описывающую все ключи, доступные в картах запросов и ответов.
Это немного устаревшее руководство (для Clojure 1.1 и Ring 0.2) показывает, как настроить некоторые инструменты разработчика для непрерывной перезагрузки кода во время разработки и отображения следов стека в браузере.
Документация по Ring API (обновленная до 1.0.0) описывает все доступные пространства имен, если вы используете Ring / Ring с помощью Leiningen.
Выводы
Мы только поцарапали поверхность Ring, но в любом случае это очень низкоуровневая библиотека, которая работает близко к HTTP-запросу.
Нам понадобится больше инструментов, чтобы получить хотя бы эквивалент API сервлета, с маршрутизацией запросов и разбором параметров из строки запроса GET. В следующих статьях мы увидим, как Compojure можно использовать поверх Ring для быстрой сборки веб-приложений так же, как работают Sinatra и Spark.