Compojure w akcji - trasowanie i obsługa parametrów
Z Jacek Laskowski - Wiki Projektanta Java EE
W artykule Clojure w aplikacji webowej z Compojure oraz Ring i Hiccup przedstawiłem szkielet aplikacji webowych Compojure zbudowany na języku Clojure. Compojure jest w tak aktywnym rozwoju, że mimo wersji 0.4.1 już dorobił się kilku bibliotek wspierających - hiccup oraz clout, a sam jest nakładką dla innej biblioteki ring. Nie stanowią one bardzo obszernych rozwiązań - szkieletów aplikacyjnych, do których przyzwyczaiłem się w Java EE i zrozumienie sensu istnienia wspomnianych stanowi dla mnie nie lada wyzwanie. A gdzie tu jeszcze umiejętne użycie.
W tym odcinku-artykule w serii o roboczej nazwie "Poznajemy Clojure praktycznie" przedstawię sposób, w jaki Compojure obsługuje trasowanie (wyznaczanie tras, tj. routing) oraz parametry z formularzy (aczkolwiek w tym odcinku formularza nie będzie i będzie jedynie przekazywanie parametrów przez adres URL).
Zakładam, że czytelnik jest zaznajomiony z treścią wspomnianego wcześniej artykułu Clojure w aplikacji webowej z Compojure oraz Ring i Hiccup i pracuje ze stworzonym tam projektem aplikacji webowej.
Spis treści |
Plik konfiguracyjny projektu - project.clj
Modyfikujemy plik konfiguracyjny projektu project.clj jak poniżej.
(defproject pl.jaceklaskowski.clojure/witaj-clojure-webapp "1.0.0-SNAPSHOT" :description "Aplikacja webowa typu 'Witaj Świecie' w Clojure z Compojure" :url "http://jaceklaskowski.pl" :main pl.jaceklaskowski.clojure.witaj-clojure-webapp.core :dependencies [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib "1.2.0"] [compojure "0.4.1"] [hiccup "0.2.7"] [ring/ring-jetty-adapter "0.3.0"]] :dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]])
Zmiany dotyczą wyłącznie wersji bibliotek.
Pobieranie zależności - lein deps
Zmieniając plik konfiguracyjny projektu project.clj zdefiniowaliśmy nowe zależności, które pobieramy za pomocą polecenia lein deps.
devmac:witaj-clojure-webapp jacek$ lein deps Copying 15 files to /Users/jacek/sandbox/witaj-clojure-webapp/lib Overriding previous definition of reference to witaj-clojure-webapp Overriding previous definition of reference to dependency.fileset Copying 2 files to /Users/jacek/sandbox/witaj-clojure-webapp/lib/dev
Edycja głównego pliku aplikacji Compojure - pl.jaceklaskowski.clojure.witaj_clojure_webapp/core.clj
Modyfikujemy plik src/pl.jaceklaskowski.clojure.witaj_clojure_webapp/core.clj, tak aby zawierał następującą treść:
(ns pl.jaceklaskowski.clojure.witaj-clojure-webapp.core "Bardzo prosta(cka) aplikacja webowa w Compojure" (:use [compojure.core] [hiccup core form-helpers page-helpers] [ring.adapter.jetty :only [run-jetty]]) (:require [compojure.route :as route])) (defn view-layout [& content] (xhtml {:lang "en"} [:head [:title "Compojure in Action"]] [:body content])) (defn display [name] (html [:h1 (str "Witaj " name ", tu Clojure z Compojure!")])) (defn view-output [name] (view-layout (display name))) (defroutes app "Tablica tras dla aplikacji webowej" (GET "/user/:name" [name] (view-output name)) (ANY "/*" [] "<b>Page not found</b>")) (defonce server (run-jetty app {:join? false :port 8080}))
I tu właśnie pojawiają się największe zmiany w aplikacji. Zacznijmy od samej góry.
Najpierw deklarujemy wykorzystywane "pakiety" - przestrzenie nazewnicze Clojure dla Compojure, Hiccup oraz Ring. W formie view-layout definiujemy strukturę docelowej strony, która zostanie wyświetlona użytkownikowi. Składa się ona z nagłówka z tytułem "Compojure in Action" oraz podaną na wejściu treścią. Każda tablica (struktura pomiędzy []) definiuje znacznik HTML w postaci ":znacznik" (dwukropek, po którym następuje nazwa znacznika". Funkcja display opiera swoje działanie na makrze html (część hiccup.core) i podobnie jak przy view-layout struktura HTML odpowiada zagnieżdżonym tablicom ze znacznikami (z dwukropkiem). Funkcja display przyjmuje pojedynczy parametr wejściowy. Funkcja view-output składa poprzednie i jej zrozumienie nie powinno stanowić problemu.
Najważniejszą częścią aplikacji opartej na Compojure jest zbudowanie trasowania za pomocą makra defroutes, które w połączeniu z funkcją run-jetty (ostatnia linia w pliku) określa, które metody HTTP, np. GET oraz adresy są obsługiwane i jak. W naszym przypadku żądanie GET dla adresu /user z opcjonalnym parametrem name powoduje wywołanie funkcji view-output. Każde inne żądanie jest obsługiwane przez makro ANY, które po prostu wyświetli wytłuszczony ciąg znaków Page not found.
Więcej informacji nt. trasowania w Compojure można znaleźć w dokumencie Routes In Detail.
Uruchomienie aplikacji webowej
Uruchamiamy aplikację za pomocą polecenia lein repl.
devmac:witaj-clojure-webapp jacek$ lein repl "REPL started; server listening on localhost:1635." 2010-09-20 20:44:55.094::INFO: Logging to STDERR via org.mortbay.log.StdErrLog 2010-09-20 20:44:55.095::INFO: jetty-6.1.14 2010-09-20 20:44:55.112::INFO: Started SocketConnector@0.0.0.0:8080 pl.jaceklaskowski.clojure.witaj-clojure-webapp.core=>
Teraz wystarczy jedynie uruchomić przeglądarkę i przetestować działanie aplikacji.
Rozpoczynamy od przypadku poprawnego podając adres http://localhost:8080/user/jacek.
Kolejny test to wykonanie dowolnego innego adresu, np. wejście na adres http://localhost:8080.
Kończy się niepowodzeniem, co było oczekiwane.
W kolejnym odcinku zaplanowałem prezentację obsługi formularza. Do następnego razu!


