#08 — aplikacje webowe

By 4 October 2014 January 4th, 2017 Kurs Javy

W dzisiejszej lekcji nauczymy się co nieco o aplikac­jach webowych, które stanow­ią zde­cy­dowaną więk­szość twor­zonych współcześnie aplikacji.

Wiedza jak pisać aplikac­je webowe jest w dzisiejszych cza­sach kluc­zowa dla pra­co­daw­ców. Jak się sama przekonasz, nie różnią się one tak bard­zo od zwykłych aplikacji, a bib­liote­ka Spring MVC tylko uproś­ci nam zadanie.

Lekcja

Choć lekc­ja ta będzie poświę­cona aplikacjom webowym, nie będziemy tutaj poz­nawać API Javy EE. Oczy­wiś­cie pole­cam samodziel­nie poczy­tać na ten tem­at, rozsz­erzyć sobie wiedzę o Servle­tach itp., ale praw­da jest taka że z ‘czys­tego’ API korzys­ta się niezwyk­le rzad­ko. Pre­cyzyj­na wiedza na ten tem­at oczy­wiś­cie przy­da­je się, ale nie jest koniecz­na do rozpoczę­cia kari­ery w IT.

Ale na pewno musimy sobie wyjaśnić czym właś­ci­wie jest Java EE :) Mówiąc najogól­niej, jest to zbiór kon­trak­tów (w postaci najczęś­ciej inter­fe­jsów), czyli ustaleń, że pewne rzeczy mają dzi­ałać tak, a nie inaczej. Dzię­ki temu aplikac­je webowe może­my rozdzielić na dwa zasad­nicze ele­men­ty — ser­w­er aplikacji oraz samą aplikację (w postaci pliku WAR). Jeśli nasza aplikac­ja korzys­ta tylko ze stan­dar­d­owych ele­men­tów (ze specy­fikacji Java EE), to może­my ją uru­chomić (zde­ploy­ować, zro­bić deploy) na dowol­nym ser­w­erze aplikacji.

Z czego składają się aplikacje webowe

Dzi­ała­ją­ca aplikac­ja webowa (tj. taka, która dzi­ała na ser­w­erze i jest dostęp­na dla użytkown­ików) w tech­nologii Java EE tak jak wspom­i­nałem wcześniej skła­da się z 2 pod­sta­wowych ele­men­tów: ser­w­era aplikacji oraz pliku WAR (częs­to ten plik nazy­wany jest aplikacją webową, bywa też określany mianem mod­ułu, sys­te­mu itp. — nie ma tutaj bard­zo ścisłych określeń).

Uwa­ga: to nie jest do koń­ca praw­da, ponieważ moż­na dołączyć lek­ki kon­tener, np. Jet­ty, do samego pliku WAR przez co nie potrze­bu­je on ser­w­era aplikacji. Ma to swo­je zale­ty, w takiej sytu­acji ser­w­er aplikacji (najczęś­ciej zubożony) jest nie­jako częś­cią samej aplikacji, więc fizy­cznie nie ma podzi­ału na 2 częś­ci, ale log­icznie moż­na nadal wyróżnić oba elementy.

Serwer aplikacji

Ser­w­er aplikacji to ‘część wspól­na’ wszys­t­kich aplikacji webowych, która zapew­nia nam pod­sta­wowe mech­a­nizmy (np. zarządzanie wątka­mi, możli­wość dynam­icznego ład­owa­nia aplikacji, auto­ryza­cję i uwierzytel­ni­an­ie (JAAS), obsługę pro­tokołu HTTP, szyfrowanie o obsługę SSL oraz inne ele­men­ty z których może­my korzys­tać za pomocą określonych API). Na rynku jest wiele ser­w­erów aplikacji, nato­mi­ast my będziemy wyko­rzysty­wali Tom­cat jako jeden z prost­szych i dzię­ki temu dzi­ała­ją­cych sprawnie także na kom­put­erze lokalnym. Z najbardziej pop­u­larnych może­my wyróżnić:

Ser­w­ery aplikacji mogą mieć uru­chomione wiele aplikacji jed­nocześnie, które są rozróż­ni­ane za pomocą tzw. kon­tek­stów. Załóżmy, że nasz ser­w­er jest uru­chomiony na naszym kom­put­erze (który ma zawsze adres local­host) i dzi­ała na domyśl­nym por­cie aplikacji webowych w Javie (8080). Adres http://localhost:8080/kontekst1/cos spowodu­je, że zostanie uru­chomiona aplikac­ja przyp­isana do kon­tek­stu o nazwie kontekst1, a w ramach tej aplikacji zostanie obsłużony adres /cos . Nazwa kon­tek­stu nadawana jest najczęś­ciej automaty­cznie na pod­staw­ie nazwy pliku WAR (np. plik aplikacja.war będzie miał kon­tekst o nazwie aplikac­ja, a plik cos.war będzie miał kon­tekst o nazwie cos ).

Aby uru­chomić plik WAR na ser­w­erze aplikacji, najczęś­ciej wystar­czy umieś­cić go w odpowied­nim kat­a­logu. W przy­pad­ku ser­w­era Tom­cat (na którym będziemy pra­cow­ali i pokazy­wali przykłady) jest to kat­a­log /webapps , w przy­pad­ku np. JBossa (z którego bard­zo częs­to korzys­ta się w przy­pad­ku aplikacji pro­duk­cyjnych) jest to kat­a­log /deployments . W przy­pad­ku innych ser­w­erów, stosow­na infor­ma­c­ja powin­na być w doku­men­tacji dostar­c­zonej przez autorów.

Plik WAR

Pli­ki WAR to nic innego jak określona struk­tu­ra kat­a­logów spakowana jako zip. Bardziej szczegółowo struk­turę omówimy sobie poniżej. To co powin­niśmy wiedzieć to to, że plik WAR powinien być kom­plet­ną aplikacją/modułem, tzn powinien zaw­ier­ać nasz kod oraz wszys­tkie zależnoś­ci (bib­liote­ki, zewnętrzne mod­uły itp), które są potrzeb­ne w naszej aplikacji.

Struktura aplikacji webowej (pliku WAR)

Tak jak wspom­ni­ałem wcześniej, plik WAR to spakowana struk­tu­ra kat­a­logów i specy­ficzne pli­ki. Przyjrzyjmy się bliżej najważniejszym kat­a­l­o­gom i plikom.

  • / — kat­a­log główny, pli­ki w tym kat­a­logu są dostęp­ne pub­licznie, należy więc uważać, żeby nie umieś­cić tam żad­nych wrażli­wych danych, np. danych dostępowych do bazy danych itp. Wyjątkiem są kat­a­lo­gi WEB-INF oraz META-INF. W tym kat­a­logu umieszcza­my treś­ci takie jak pli­ki jsp (nie będziemy z nich korzys­tać w taki sposób), grafi­ki uży­wane w inter­fe­jsie, skryp­ty JS, arkusze styli CSS itp. Zawartość tego kat­a­logu jest reprezen­towana w naszym pro­jek­cie Mavenowym poprzez kat­a­log /src/main/webapp
  • /WEB-INF — to kat­a­log, w którym jest nasz skom­pi­lowany kod, a także zawartość kat­a­logu /src/main/resources z naszego pro­jek­tu Mavenowego. Poza tym wewnątrz znajdziemy: 
    • web.xml — główny (i tak naprawdę jedyny wyma­gany) plik aplikacji webowej, określony w stan­dard­zie JavaEE. Defini­u­je­my w nim Servle­ty, Lis­ten­ery, Fil­try itp. My będziemy go uży­wać tylko po to, żeby uru­chomić Springa ‑w skró­cie, powiemy, że wszys­tkie zapy­ta­nia mają być obsługi­wane przez Servlet dostar­czany przez Springa, oraz wskaże­my gdzie zna­j­du­je się nasza konfiguracja
    • class­es — skom­pi­lowane nasze klasy
    • lib — bib­liote­ki i zależnoś­ci w postaci plików JAR (np. tutaj zna­jdziemy bib­liote­ki Springa)
  • /META-INF — w tym kat­a­logu najczęś­ciej zna­jdziemy pli­ki których sami tam nie umieszcza­l­iśmy ;) Bib­liote­ki cza­sem prze­chowu­ją tutaj kon­fig­u­rację, deskryp­to­ry, opisy itp. Na tą chwilę nie będziemy się nim zajmować.

MVC

Zan­im prze­jdziemy do Springa powiemy sobie parę słów czym właś­ci­wie jest MVC. To akro­n­im od Mod­el — View — Con­troller, co sym­bol­izu­je ‘trójpodzi­ał’ aplikacji. Idea jest prost­sza niż to brz­mi ;) Chodzi o to że pisząc funkcjon­al­ność (np. wyp­isy­wanie listy kotów w naszej aplikacji) wyróż­ni­amy trzy jej rozdzielne elementy:

  • mod­el — czyli tzw. domenę, są to obiek­ty które reprezen­tu­ją pewien frag­ment rzeczy­wis­toś­ci (np. w naszej aplikacji takim obiek­tem jest Kot) oraz pow­iązane ele­men­ty (np. kod zapisujący/odczytujący dane naszych kotów z bazy danych)
  • view — wido­ki to to, co widzi użytkown­ik. Są to najczęś­ciej frag­men­ty kodu HTML wzbo­ga­cone o dodatkowe ele­men­ty języ­ka (np. żeby wyświ­etlić dynam­iczne informacje)
  • con­troller — to tzw. kon­trol­ery, czyli logi­ka, która stoi za naszy­mi stron­a­mi — inny­mi słowy kod który łączy mod­el (bazę danych) z widoka­mi (użytkown­ikiem).

Tutaj uwa­ga! W aplikac­jach częs­to uży­wa się tzw. ser­wisów (czyli klas, które ofer­u­ją funkcjon­al­ność czys­to biz­ne­sową, np. wyślij emaila, wywołaj jak­iś inny pro­gram). Ser­wisy są wywoły­wane przez kon­trol­ery i w zależnoś­ci od pode­jś­cia mogą być uwzględ­ni­ane w poję­ciu ‘kon­trol­ery’ lub nie — to zależy tak naprawdę od przyjętej nomenklatury.

W naszym przy­pad­ku będziemy wyko­rzysty­wać Spring­MVC który poma­ga nam połączyć powyższe ele­men­ty w jed­ną całość i ograniczyć ilość pisanego kodu ‘boil­er­plate’ (to kod, który nie real­izu­je stricte funkcjon­al­noś­ci, a służy jedynie temu, żeby całość mogła dzi­ałać ze sobą — przykła­dem są np. get­tery i settery).

Poniższy dia­gram obrazu­je zależnoś­ci i sposób inter­akcji pomiędzy tymi komponentami:

Zależnoś­ci pomiędzy ele­men­ta­mi MVC. Źródło: Schemat inter­akcji pomiędzy poszczegól­ny­mi ele­men­ta­mi we wzor­cu MVC.  Źródło: WIKIPEDIA

Spring MVC

Od razu zas­trzegam że to, jak uży­wać Spring­MVC omówimy w kole­jnej lekcji, dzisi­aj będzie tylko kon­cepc­ja oraz kil­ka informacji :)

Przede wszys­tkim, czym jest i co nam daje: Spring Frame­work to obec­nie najpop­u­larniejszy frame­work do tworzenia aplikacji w języku Java. Do jego sukce­su przy­czyniła się przede wszys­tkim elasty­czność — moż­na go stosować niemalże w każdym rodza­ju aplikacji, a jed­nocześnie pre­cyzyjnie kon­fig­urować jego dzi­ałanie. Frame­work ten zbu­dowany jest wokół zasady con­ven­tion-over-con­fig­u­ra­tion, tzn. nie musimy nic kon­fig­urować i wtedy zostaną przyjęte sen­sowne wartoś­ci domyślne. Najczęś­ciej jest to super rozwiązanie, pozwala­jące znacznie ograniczyć ilość pra­cy przy pro­jek­cie. Od jakiegoś cza­su głównym sposobem na ‘współprace’ ze Springiem są adno­tac­je, czyli np. @Component nad nazwą klasy (adno­tac­je omówimy w kole­jnej lekcji).

To, co daje nam Spring to przede wszys­tkim kon­tener IoC (Inver­sion of Con­trol) — oznacza to w uproszcze­niu (i nie do koń­ca w zgodzie z rzeczy­wis­toś­cią — ale na potrze­by kur­su może­my przyjąć że tak jest) że w prze­ci­wieńst­wie do ‘stan­dar­d­owej’ sytu­acji, w której to klasa sama musi zad­bać o inicjowanie potrzeb­nych jej kom­po­nen­tów, to kon­tener dba o tworze­nie odpowied­nich obiek­tów i ich ‘wstrzyki­wanie’ (tzw. DI — Depen­den­cy Injec­tion, to jed­na z cech kon­tenera IoC), czyli ustaw­ian­ie odpowied­nich pól klasy właś­ci­wy­mi wartościami.

Spring MVC to ‘rozsz­erze­nie’ Frame­wor­ka Spring o wspar­cie dla aplikacji webowych (m.in obsłu­ga adresów URL, przesyła­nia danych poprzez for­mu­la­rze itp) dzię­ki czemu tworze­nie aplikacji webowej jest prost­sze niż kiedykolwiek.

W przy­pad­ku Spring MVC spotkamy się też z poję­ciem tzw. view resolvera — to spec­jal­na klasa, która otrzy­mu­je nazwę widoku do wyświ­etle­nia oraz dane które przekazu­je­my do tego widoku (obiekt typu Mod­e­lAnd­View) i na tej pod­staw­ie generu­je widok, który widzi użytkown­ik. Omówimy to od strony prak­ty­cznej poz­na­jąc kontrolery.

To co jeszcze należy wiedzieć o Springu to kil­ka pojęć:

  • bean — to obiekt dowol­nego typu, który jest zarządzany przez Spring’a a tym samym podle­ga wstrzyki­wa­niu (czyli moż­na go wstrzyknąć w dowol­ny obiekt z uży­ciem adnotacji)
  • kom­po­nent / stereo­typ — to adno­tac­ja, która mówi że obiekt danej klasy ma być zarządzany przez Springa (inny­mi słowy: mówimy Springowi żeby utworzył beana o takim typie)
  • com­po­nent-scan — pro­ce­du­ra, którą Spring wykonu­je na początku (pod­czas inicjowa­nia aplikacji) i która pole­ga na ‘prze­jrze­niu’ wszys­t­kich dostęp­nych oraz znalezie­niu tych, które są oznac­zone jako kom­po­nen­ty (mają określony stereotyp)
  • view resolver — patrz wyżej ;)

To tyle teorii, do prak­ty­ki prze­jdziemy w kole­jnej lekcji :)

Materiały dodatkowe / dokumentacja

  1. Opis pliku web.xml i możli­woś­ci jego kon­fig­u­racji (EN)
  2. Opis pliku WAR (EN)
  3. Ref­er­ence do Spring­MVC (EN)
  4. Szy­b­ki tuto­r­i­al Spring MVC (EN) — spoil­er! to będziemy omaw­iać w kole­jnej lekcji dokładniej

Zadanie

Dzisiejsze zadanie prak­ty­czne będzie dość proste:

  • dodaj do pro­jek­tu Maven mod­uł koty-webapp (tak, aby był typu WAR)
  • do pro­jek­tu koty-webapp dodaj zależnoś­ci koty-domain oraz koty-appli­ca­tion (pamię­taj, że zależnoś­ci są prze­chod­nie — więc wystar­czy dodać tylko jed­ną z nich (wiesz którą, praw­da? :) ) a dru­ga będzie ‘w kom­ple­cie’ — jako zależność zależności
  • do pro­jek­tu koty-webapp dodaj zależnoś­ci do spring MVC oraz Spring con­text w tych samych wer­s­jach, co spring-core

Dodatkowo pole­cam zapoz­nać się z tuto­ri­ala­mi Spring MVC lub ofic­jal­nym get­ting start­ed — ułatwi to następ­ną lekcję :)

UWAGA!! Rozwiązanie tego zada­nia nie jest jeszcze pełno­prawną aplikacją webową! Braku­je przede wszys­tkim pliku web.xml, który jest niezbęd­ny do uru­chomienia aplikacji na ser­w­erze. Plik ten doda­je­my dopiero w lekcji 9. Poniższego rozwiąza­nia NIE DA SIĘ uru­chomić bez modyfikacji.

zip Pobierz rozwiązanie tego zadania

Licencja Creative Commons

Jeśli uważasz powyższą lekcję za przy­dat­ną, mamy małą prośbę: pol­ub nasz fan­page. Dzię­ki temu będziesz zawsze na bieżą­co z nowy­mi treś­ci­a­mi na blogu ( i oczy­wiś­cie, z nowy­mi częś­ci­a­mi kur­su Javy). Dzięki!