Статьи

Веб-приложение в Clojure: отправная точка

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.