informatyka java ee 6 programowanie aplikacji www krzysztof rychlicki kicior ebook

background image

Java

EE 6

Programowanie aplikacji WWW

Szybko i bez kïopotów poznaj Java Enterprise Edition

Naucz siÚ praktycznie tworzyÊ ciekawe aplikacje WWW

DoïÈcz do elity programistów nowoczesnych rozwiÈzañ webowych

È

Ú

Ú

ï

È

Ú

È

È

ĝ

Ă

È

Ú

ĝ

ĝ

ĂÊ

È ñ

Ú

È ĝ

Ă

ï

È

Ú

Ú

È

È

Ă

ĝ

Ă

Ú

È

È

Ú

Ă

ĝ

ĝ

Ê

ïÈ

È È

È

Ú

Ú

ï

Úĝ

Ú

ï

È

Ă

Ă

È

Ê Ă

Ú

È

ě

ï

ï

ï

ĂÊ

Ă

Ú Ú

ï

Èĝ

Ú

È

ĝ

ĂÊ

Ú È

ġ Ê

Ú

Ă

ï Ă

Ú

Ú

È

ġ È

ĝ

Ă

È

ï Ă

Ê

È

Ă

Ú

ÈÊ

Ú

Èĝ Ú

ĝ

ï

Ú

Ă

Krzysztof Rychlicki-Kicior

Juĝ dziĂ siÚgnġ po jedyne kompendium wiedzy na temat Java EE!

’

k

È

ĝ

Ú

Ú

ï

background image

Java EE 6.
Programowanie
aplikacji WWW

Autor:

Krzysztof Rychlicki-Kicior

ISBN: 978-83-246-2659-5
Format: 158×235, stron: 232

• Szybko i bez k³opotów poznaj Java Enterprise Edition
• Naucz siê praktycznie tworzyæ ciekawe aplikacje WWW
• Do³¹cz do elity programistów nowoczesnych rozwi¹zañ webowych

Ju¿ dziœ siêgnij po jedyne kompendium wiedzy na temat Java EE!

Java Enterprise Edition to standard tworzenia aplikacji biznesowych wykorzystuj¹cych
jêzyk Java. Opracowany przez firmê Sun Microsystems, dzia³a w oparciu o wielowarstwow¹
architekturê komponentow¹, oferuj¹c programistom bardzo rozbudowane mo¿liwoœci
tworzenia oprogramowania funkcjonuj¹cego na niemal dowolnym sprzêcie, w ka¿dym
systemie operacyjnym, z wykorzystaniem licznych serwerów aplikacji. Du¿a popularnoœæ
rozwi¹zañ Java EE i coraz powszechniejszy dostêp do technologii WWW sprawiaj¹,
¿e programiœci sprawnie pos³uguj¹cy siê tego rodzaju narzêdziami rzadko figuruj¹ na
listach osób poszukuj¹cych pracy, a jeœli ju¿ jakimœ cudem siê na nich znajd¹, bardzo
szybko otrzymuj¹ atrakcyjne propozycje zatrudnienia. Nauka swobodnego poruszania
siê w tym œrodowisku mo¿e te¿ byæ wspania³¹, poszerzaj¹c¹ horyzonty przygod¹,
a gdy poznasz platformê Java EE, bêdziesz dysponowa³ potê¿nym narzêdziem,
u³atwiaj¹cym tworzenie nawet najbardziej skomplikowanych aplikacji internetowych
w bardzo efektywny i szybki sposób.

Studenci, programiœci i hobbyœci pragn¹cy poznaæ œrodowisko Java Enterprise Edition
czêsto napotykaj¹ problem ze znalezieniem solidnych Ÿróde³ wiedzy, które pozwoli³yby
im szybko i ³atwo wejœæ w œwiat tej coraz bardziej popularnej technologii. Lukê tê
z powodzeniem wype³nia ksi¹¿ka „Java EE 6. Programowanie aplikacji WWW”.

Dziêki niej wszyscy zainteresowani tematem zyskaj¹ mo¿liwoœæ poznania Java EE od
podstaw i zdobycia praktycznej wiedzy, na podstawie której bêd¹ mogli rozwijaæ swoje
umiejêtnoœci programistyczne w przysz³oœci. Ten podrêcznik pozwala na szybkie
rozpoczêcie przygody z tworzeniem aplikacji webowych, skutecznie wprowadzaj¹c
w zagadnienia wykorzystywanych przy tym platform i mechanizmów, lecz nie pomijaj¹c
te¿ informacji o charakterze ogólnym. Jeœli niewiele mówi¹ Ci skróty JSP, JPA, JSF
czy JPQL, a chcia³byœ zmieniæ ten stan rzeczy, bez w¹tpienia powinieneœ siêgn¹æ po tê
ksi¹¿kê, podobnie jak wszystkie osoby zainteresowane bezproblemowym u¿ywaniem
ca³ego spektrum nowoczesnych narzêdzi oferowanych przez œrodowisko Java EE.

• Tworzenie serwletów
• Zastosowanie szablonów JSP
• Integracja danych z aplikacjami za pomoc¹ mechanizmu JPA
• U¿ywanie interfejsów i komponentów
• Korzystanie z technologii JSF
• Uniwersalny i wygodny dostêp do danych, czyli jêzyk JPQL
• Praktyczne przyk³ady realizacji

Spraw, aby tworzenie aplikacji WWW z wykorzystaniem Java EE nie mia³o przed Tob¹ tajemnic

background image

Spis tre

Ĉci

CzöĈè I

Podstawy ....................................................................... 7

Rozdziaä 1. Java EE — naprawdö krótkie wprowadzenie ...................................... 9

Web vs Enterprise ........................................................................................................... 10
Serwery aplikacji ............................................................................................................ 11
Streszczenie, czyli krótki przewodnik po niniejszej publikacji ...................................... 11

Serwlety — na dobry początek ................................................................................. 11
Deskryptor wdroĪenia .............................................................................................. 12
JSP — HTML + Java ............................................................................................... 13
JPA — czas na dane! ................................................................................................ 13
JSF — wyĪszy poziom prezentacji ........................................................................... 13
Facelets ..................................................................................................................... 14

Rozdziaä 2. Pierwsza aplikacja webowa ............................................................ 15

Integrowanie Tomcata z Netbeansem ............................................................................. 16
Pierwsza aplikacja .......................................................................................................... 17
Dodawanie nowych elementów ...................................................................................... 18
Pierwszy serwlet? ........................................................................................................... 20

Rozdziaä 3. Serwlet — na dobry poczñtek ......................................................... 25

ĩycie serwletu ................................................................................................................ 25
Serwlet pod lupą ............................................................................................................. 26
ĩądanie — odpowiedĨ .................................................................................................... 27

Przesyáanie odpowiedzi ............................................................................................ 29
Om nom nom, czyli ciasteczka w peánej krasie ........................................................ 31
Sesje — nie tylko dla studentów .............................................................................. 31

Konfiguracja w kodzie Javy — moĪna tego uniknąü ...................................................... 33

Parametry serwletów ................................................................................................ 34
Kontekst serwletów .................................................................................................. 35

Trzech muszkieterów? .................................................................................................... 36

Atrybuty a mnogoĞü ĪądaĔ ....................................................................................... 36

Sáuchowisko ................................................................................................................... 39

ServletContextListener ............................................................................................. 39
ServletContextAttributeListener ............................................................................... 39
ServletRequestAttributeListener i ServletRequestListener ....................................... 39
HttpSessionAtributteListener i HttpSessionListener ................................................ 40

background image

4

Java EE 6. Programowanie aplikacji WWW

HttpSessionBindingListener ..................................................................................... 40
Sesja + wiele JVM = HttpSessionActivationListener ............................................... 40

Filtry ............................................................................................................................... 41

Techniczny aspekt filtrów ........................................................................................ 41
Konfiguracja filtrów w pliku web.xml ..................................................................... 42

Rozdziaä 4. JSP — gdy out.println() nie wystarcza ............................................. 45

Zacznijmy od początku, czyli JSP w Ğwiecie serwletów ................................................ 46

Pliki JSP dostĊpne bezpoĞrednio .............................................................................. 46
Pliki JSP wywoáywane z poziomu serwletów .......................................................... 46

Pochodzenie JSP — dziedzictwo serwletów .................................................................. 47
Pierwsze kroki w JSP ..................................................................................................... 47

Doceniü wygodĊ, czyli jak to lat temu kilka bywaáo… ............................................ 50

Expression Language — elegancja i wygoda ................................................................. 54

Remedium — warto byáo czekaü! ............................................................................ 55
DostĊp do obiektów w jĊzyku EL ............................................................................. 56
Beany, czyli ziarna — kult kawy wiecznie Īywy ..................................................... 57
Ziarna + EL = kolejne uáatwienie ............................................................................. 58
Ziarna, mapy i co dalej? ........................................................................................... 59
EL — nie tylko atrybuty ........................................................................................... 59

Akcje JSP ....................................................................................................................... 61

Include vs Forward — odsáona druga ....................................................................... 62
Akcje + ziarna = kolejne potĊĪne narzĊdzie ............................................................. 63
Dynamiczne generowanie elementów ...................................................................... 66

Rozdziaä 5. JSTL — wisienka na torcie JSP ....................................................... 69

Skrzynka z narzĊdziami .................................................................................................. 69
RdzeĔ .............................................................................................................................. 70

c:out .......................................................................................................................... 70
Ale to juĪ byáo, czyli c:set ........................................................................................ 72
Czwarty muszkieter .................................................................................................. 73
Kontrola sterowania ................................................................................................. 73
PĊtelka do kompletu ................................................................................................. 75
Wyjątki + JSP = … .................................................................................................. 76

Adresy URL — same káopoty ........................................................................................ 77

Adresy URL bez tajemnic ........................................................................................ 77
Tajemnica sesji… ..................................................................................................... 78

Trzech tenorów ............................................................................................................... 79
Na deser — funkcje! ....................................................................................................... 80

Przez kolekcje do serca ............................................................................................ 80
Funkcje áaĔcuchowe ................................................................................................. 81

Podsumowanie ................................................................................................................ 82

CzöĈè II Frameworki webowe ..................................................... 83

Rozdziaä 6. JavaServer Faces ........................................................................... 85

Frameworki — kolejny dowód na lenistwo czáowieka ................................................... 85
JSF — kanonu ciąg dalszy .............................................................................................. 86

JSF, czyli MVC w praktyce ...................................................................................... 87
Kontroler — uniwersalny spawacz ........................................................................... 88

Maáe zanurzenie .............................................................................................................. 88

Pierwsze przykáady .................................................................................................. 89

Aplikacja Notowania gieádowe ....................................................................................... 90

Tajemniczy zapis — # vs $ ...................................................................................... 95
Notowania historyczne, czyli kolekcja w kolekcji ................................................... 97

background image

Spis treĈci

5

Najpierw szablon, póĨniej treĞü ................................................................................ 98
Klient szablonu ......................................................................................................... 99
Przygotowania… .................................................................................................... 100
Czas na obliczenia! ................................................................................................. 103
Maáy zastrzyk ......................................................................................................... 105

JSF — komponenty, komponenty, komponenty! ......................................................... 106

Output — (prawie) wszystko, czego do szczĊĞcia potrzeba ................................... 107
UIInput — teraz do szczĊĞcia nie brakuje juĪ nic ................................................... 108
Powrót do szarej rzeczywistoĞci… ......................................................................... 112

Zasady dziaáania JSF .................................................................................................... 115

Przykáadowa aplikacja — maszyna licząca ............................................................ 115
Przywrócenie widoku (1) ....................................................................................... 118
Pobranie danych z Īądania (2) ................................................................................ 119
Walidacja (3) .......................................................................................................... 119
Aktualizacja wartoĞci w modelu (ziarnach — 4) .................................................... 120
Wywoáanie zadeklarowanych uprzednio metod (5) ............................................... 120
Renderowanie odpowiedzi (6) ................................................................................ 120

Cykl Īycia w praktyce .................................................................................................. 120
Podsumowanie .............................................................................................................. 121

Rozdziaä 7. Konwertowanie i walidacja ........................................................... 123

Uroki transformacji ...................................................................................................... 123

Konwertery standardowe ........................................................................................ 124
Piszemy konwerter! ................................................................................................ 126

Walidator — nieodáączny partner konwertera .............................................................. 130

Walidatory — prawie jak konwertery .................................................................... 131
Walidacja niestandardowa — jak zawsze wiĊcej pracy .......................................... 132

CzöĈè III Obsäuga danych .......................................................... 135

Rozdziaä 8. JPA, czyli ORM + Java .................................................................. 137

DostĊp do danych w Javie ............................................................................................ 137

OĞwiecenie ............................................................................................................. 138

Pierwszy przykáad ........................................................................................................ 139

ZaáoĪenia ................................................................................................................ 139
Realizacja ............................................................................................................... 139
Tworzenie projektu ................................................................................................ 140
Hibernate a JPA — co i jak w ORM-owym Ğwiecie .............................................. 141
Pierwsza klasa encji ............................................................................................... 141
Jednostka utrwalania .............................................................................................. 145
Graficzna strona aplikacji ....................................................................................... 146
Dodawanie przychodni ........................................................................................... 150
EntityManager i spóáka… ...................................................................................... 152
MenedĪer encji — elegancki dostĊp != áatwa sprawa ............................................ 153
Nudni sáuchacze — nareszcie przydatni! ............................................................... 156
C juĪ jest, czas na RUD .......................................................................................... 158
Niewiele Ci mogĊ daü… (póki nie pozwolisz mi zaprezentowaü danych) ............. 158
Sáuchacz akcji vs akcja — starcie numer 2 ............................................................. 160
Istotny drobiazg — nasza aplikacja to niemowa! ................................................... 162

Rozdziaä 9. Zwiñzki miödzy encjami — jedna tabela to za maäo! ...................... 165

Przychodnia… i co dalej? ............................................................................................. 165

Związki miĊdzy tabelami — krótkie przypomnienie .............................................. 165
Związki SQL w praktyce ........................................................................................ 166
Jeden do wielu, wiele do jednego ........................................................................... 167

background image

6

Java EE 6. Programowanie aplikacji WWW

Wiele do wielu — najwyĪszy stopieĔ wtajemniczenia ........................................... 167
Dodajemy tabele do bazy ....................................................................................... 168

Encje klas Javy — czas na związki! ............................................................................. 170

Encja Przychodnia — zmiana na lepszy model ...................................................... 171
Czas na nowoĞci! .................................................................................................... 172
Wizyta — encja JPA w peánej krasie ..................................................................... 178

CRUD dla lekarza — to juĪ byáo, ale nie do koĔca ...................................................... 183

Nowy lekarz — nowe pole, duĪa zmiana ............................................................... 184
Magikonwersja ....................................................................................................... 185
Ziarnko do ziarnka i zbierze siĊ aplikacja .............................................................. 186
Kolejne metody ziarna LekarzBean… .................................................................... 188
Na zakoĔczenie — edycja ...................................................................................... 189
Pacjenci — suplement ............................................................................................ 191

Danie gáówne: all in one, czyli wizyty! ........................................................................ 192

Od czegoĞ trzeba zacząü, czyli zmiany ................................................................... 193
Dodawanie wizyty .................................................................................................. 196
Ostatnie ziarno ....................................................................................................... 197
Edycja i usuwanie — powrót ................................................................................. 200
Koniec coraz bliĪej, czyli edycja w peánej krasie ................................................... 201

Podsumowanie .............................................................................................................. 202

Rozdziaä 10. JPQL i jego moĔliwoĈci ................................................................. 203

Prawie jak SQL… „prawie” robi róĪnicĊ ..................................................................... 203
Podstawy ...................................................................................................................... 204

Pobieranie z wariantami ......................................................................................... 204
JPQL a atrybuty záoĪone i null ............................................................................... 206
Nieco wiĊcej o SELECT ........................................................................................ 207
Funkcje obliczeniowe ............................................................................................. 208
Operacje niezwiązane z pobieraniem ..................................................................... 209

Mechanizmy zaawansowane ........................................................................................ 209

JOIN na lewo, JOIN na prawo… ............................................................................ 210
Grupowanie i sortowanie ........................................................................................ 211
Podzapytania — prawdziwa moc ........................................................................... 212

Podsumowanie .............................................................................................................. 213

Dodatki ..................................................................................... 215

Dodatek A Instalacja serwera Apache Tomcat ............................................... 217

Pobranie ........................................................................................................................ 217
Konfiguracja ................................................................................................................. 217

Dodatek B Bibliografia .................................................................................. 219

Skorowidz ....................................................................................................... 221

background image

Rozdziaä 3.

Serwlet
— na dobry pocz

ñtek

Aplikacja z poprzedniego rozdziaáu wprowadziáa kilka istotnych elementów, których
omawianiem zajmiemy siĊ w przeciągu najbliĪszych trzech rozdziaáów. Rozpocznie-
my od podstawy podstaw, czyli elementu, który jest wykorzystywany poĞrednio lub
bezpoĞrednio we wszystkich aplikacjach webowych — mowa o serwlecie.

Serwlet, czyli klasa rozszerzająca moĪliwoĞci serwera aplikacji, moĪe byü traktowany
jako pojĊcie niesáychanie ogólne. Praktycznie jedynym istotnym wymaganiem sta-
wianym serwletom jest dziaáanie w trybie Īądanie — odpowiedĨ — serwlet powinien
generowaü treĞü odpowiedzi w oparciu o to, co otrzyma w Īądaniu. W poprzednim
rozdziale spotkaáeĞ siĊ z jednym z typowych zastosowaĔ serwletów — generowaniem
kodu HTML. Nie jest to jednak w Īadnym razie kres ich moĪliwoĞci — nic nie stoi
na przeszkodzie, aby za pomocą serwletów generowaü zarówno dane tekstowe (np.
w formacie XML), jak i dane binarne (np. pliki wykonywalne, obrazy, etc.). Zanim
jednak zabierzemy siĊ za praktyczne przykáady (pierwszy z nich mogáeĞ przeanali-
zowaü w poprzednim rozdziale), konieczne jest krótkie wprowadzenie teoretyczne,
w którym dowiesz siĊ, jak serwlet wspóápracuje z serwerem aplikacji, a takĪe jakie
podstawowe opcje związane z serwletami moĪna ustawiü w pliku web.xml.

ēycie serwletu

Gdy uruchamiasz zwykáą aplikacjĊ, graficzną lub konsolową, w swoim systemie ope-
racyjnym, moĪesz w wiĊkszoĞci przypadków okreĞliü precyzyjnie, kiedy rozpoczyna
siĊ, a kiedy koĔczy jej dziaáanie. W przypadku popularnych technologii dynamicznych
stron internetowych (np. PHP) pliki są interpretowane na bieĪąco (aczkolwiek istnieje
moĪliwoĞü ich poĞredniej kompilacji). Jak moĪna opisaü cykl Īycia serwletu?

Zacznijmy od klasy w takiej postaci, jaką juĪ znamy — nieskompilowanego kodu Ĩró-
dáowego. Zanim serwer zostanie uruchomiony, wszystkie pliki klas muszą zostaü pod-
dane kompilacji. Powstaáe pliki (o rozszerzeniu .class) są kopiowane do odpowiednich

background image

26

CzöĈè I i Podstawy

katalogów. Dopiero wtedy serwer moĪe byü uruchomiony, na nowo lub ponownie. Na
szczĊĞcie w nowszych wersjach serwerów aplikacji (np. Apache Tomcat 6) istnieje
moĪliwoĞü automatycznego wykrywania i aktualizacji klas w trakcie dziaáania serwera.

Gdy uruchamiasz serwer aplikacji, z punktu widzenia naszego serwletu nie dzieje siĊ
nic istotnego. NastĊpuje wtedy, rzecz jasna, inicjalizacja samego serwera, a takĪe nie-
których ustawieĔ caáej aplikacji webowej. Sam serwlet pozostaje jednak nienaruszo-
ny. Caáa zabawa zaczyna siĊ, gdy dowolny uĪytkownik Twojej aplikacji po raz pierw-
szy spróbuje z niego skorzystaü. Serwer wykonuje wtedy nastĊpujące czynnoĞci:



zaáadowanie klasy serwletu,



utworzenie instancji serwletu,



wywoáanie metody

init()

,



wywoáanie metody

service()

.

Gdy serwlet znajdzie siĊ w trakcie wywoáania metody

service()

, moĪe on rozpocząü

normalną obsáugĊ ĪądaĔ. Od tego momentu w przypadku otrzymania przezeĔ dowol-
nego Īądania HTTP, nastąpi próba wywoáania odpowiedniej metody serwletu, wedáug
schematu

nazwa

/

doNazwa()

, np.

GET

/

doGet()

,

POST

/

doPost()

, itd.

Sporo pracy, nieprawdaĪ? Na szczĊĞcie do obowiązków programisty naleĪy obsáuga
wybranych metod ze sáowem

do

w nazwie. JeĞli wiĊc chcesz, aby serwlet obsáugiwaá

tylko Īądanie

GET

, zadeklaruj jedynie metodĊ

doGet()

.

W przypadku klasy serwletu utworzonej przez Netbeans, proces tworzenia serwletu
zostaá uproszczony jeszcze bardziej. Twórcy szablonu zaáoĪyli (skądinąd sáusznie), Īe
znamienita wiĊkszoĞü programistów korzysta jedynie z metod HTTP

GET

i

POST

. Z tego

wzglĊdu w klasie serwletu są przesáaniane dwie metody —

doGet()

i

doPost()

, które

odwoáują siĊ do jednej i tej samej metody — o nazwie

processRequest()

. Z jednej

strony uáatwia to Īycie w wiĊkszoĞci sytuacji, z drugiej jednak mogą siĊ zdarzyü sytu-
acje, w których inaczej chcemy zareagowaü w przypadku Īądania

GET

, a inaczej w przy-

padku

POST

. W takiej sytuacji naleĪy usunąü wygenerowany mechanizm i napisaü wáa-

sne metody obsáugi

doGet()

i/lub

doPost()

.

Serwlet pod lup

ñ

Przed chwilą poznaáeĞ przepáyw sterowania w serwlecie; najwyĪsza pora, abyĞ zapo-
znaá siĊ pokrótce z kluczowymi klasami powiązanymi z obsáugą serwletów. OmówiĊ
jedynie najwaĪniejsze elementy; warto je zapamiĊtaü, poniewaĪ bĊdą siĊ one pojawiaü
takĪe w dalszych przykáadach, ilustrujących kolejne omawiane technologie.

Jak juĪ wspomniaáem, serwlety, którymi zajmujemy siĊ w niniejszej ksiąĪce, dziedzi-
czą po klasie

HttpServlet

. Ze wzglĊdu na fakt, Īe serwlet z zaáoĪenia jest konstrukcją

niezwykle uniwersalną, w hierarchii dziedziczenia pojawiają siĊ dodatkowe elementy,
które ową uniwersalnoĞü wprowadzają. Oto krótki opis elementów hierarchii dziedzi-
czenia, począwszy od tych najbardziej ogólnych:

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

27



Interfejs

Servlet

— okreĞla najwaĪniejsze metody, które muszą

implementowaü wszystkie serwlety. Metody te są niezaleĪne od stosowanych
protokoáów przesyáania danych, a dotyczą one gáównie zarządzania cyklem
Īycia serwletu (

init()

,

service()

,

destroy()

).



Abstrakcyjna klasa

GenericServlet

— podstawowa implementacja

interfejsów

Servlet

i

ServletConfig

, dająca dostĊp do parametrów i ustawieĔ

serwletu. Klasa ta zawiera proste implementacje metod obu interfejsów,
dziĊki czemu stanowi podstawĊ dla klasy

HttpServlet

i wszystkich innych

klas serwletów.



Klasa

HttpServlet

— to wáaĞnie po tej klasie bĊdziesz dziedziczyá, tworząc

wáasne serwlety. Poza wáasnymi implementacjami metod ze wspomnianych
wczeĞniej interfejsów, klasa

HttpServlet

udostĊpnia metody

do*

, czyli

doGet()

,

doPost()

etc. DziĊki temu we wáasnych serwletach musisz

zdefiniowaü jedynie te metody, które Twój serwlet zamierza obsáugiwaü.

Protokóá HTTP zawiera definicje oĞmiu metod:

GET

,

POST

,

PUT

,

HEAD

,

OPTIONS

,

TRACE

,

DELETE

,

CONNECT

. Serwlety mogą obsáugiwaü wszystkie metody, na wyĪej omówionej

zasadzie. W praktyce zdecydowanie najczĊĞciej stosuje siĊ metody

GET

i

POST

i to na

nich skupimy siĊ w dalszej czĊĞci tego rozdziaáu.

ēñdanie — odpowiedĒ

Mimo niewątpliwie istotnej roli klasy

HttpServlet

, w trakcie pracy z serwletami czĊ-

Ğciej przyjdzie Ci zapewne korzystaü z interfejsów

HttpServletRequest

/

HttpServlet

´Response

. Reprezentują one odpowiednio obiekty Īądania i odpowiedzi, przekazy-

wane do metod

doGet()

,

doPost()

etc. Peány nagáówek metody

doGet()

wygląda na-

stĊpująco:

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, java.io.IOException

Twoim zadaniem jest takie zdefiniowanie metod

do*

, aby generowaáy one odpowiedĨ,

zazwyczaj zaleĪną od przesáanych parametrów. Wszystkie niezbĊdne metody znajdziesz
w dwóch wyĪej wspomnianych klasach. Zacznijmy od interfejsu

HttpServletRequest

— to na jego podstawie bĊdziemy w kolejnych przykáadach generowaü odpowiedzi
przesyáane za pomocą interfejsu

HttpServletResponse

.

Niemal wszystkie metody

HttpServletRequest

są faktycznie przydatne, niemniej w tym

miejscu omówimy metody najistotniejsze z punktu widzenia samych serwletów:

 Object getParameter(String nazwa)

— pobiera parametr o danej nazwie

przesáany w Īądaniu.

 Enumeration<String> getParameterNames()

— pobiera nazwy wszystkich

parametrów znajdujących siĊ w danym Īądaniu.

 String getRemoteUser()

— zwraca login uwierzytelnionego uĪytkownika

lub

null

, w przypadku braku uwierzytelnienia.

background image

28

CzöĈè I i Podstawy

 Cookie[] getCookies()

— zwraca tablicĊ ciasteczek — specjalnych plików

przechowywanych na komputerze uĪytkownika.

 String getQueryString()

— zwraca áaĔcuch parametrów, przesáanych

w adresie URL (za znakiem zapytania).

 String getHeader(String nazwa)

— zwraca wartoĞü nagáówka HTTP

o podanej nazwie.

 int getIntHeader(String nazwa)

— zwraca wartoĞü nagáówka HTTP

o podanej nazwie jako liczbĊ caákowitą.

 long getDateHeader(String nazwa)

— zwraca wartoĞü nagáówka HTTP

o podanej nazwie jako liczbĊ milisekund, począwszy od początku epoki
(1 stycznia 1970 roku). WartoĞü ta moĪe byü przekazana w konstruktorze
klasy

Date

.

 String getContextPath()

— zwraca ĞcieĪkĊ kontekstu aplikacji.

 String getServletPath()

— zwraca ĞcieĪkĊ dostĊpu do serwletu.

 String getPathInfo()

— zwraca dodatkowe informacje zawarte w ĞcieĪce.

Trzy ostatnie metody są ze sobą związane, poniewaĪ zwracają one kolejne elementy
adresu URL, wykorzystanego do wykonania Īądania. Przeanalizujmy poniĪszy przy-
káad, prezentujący wiadomoĞü o okreĞlonym identyfikatorze:

http://localhost:8080/MojaAplikacja/serwlety/info/235/

Pomijamy oczywiĞcie nazwĊ protokoáu (http) i nazwĊ serwera z portem (localhost:8080).
Zostaje nam wiĊc ciąg:

/MojaAplikacja/serwlety/info/235/
Metoda getContextPath() zwraca fragment adresu okreħlajæcy naszæ aplikacjú:
/MojaAplikacja

ĝcieĪka do kontekstu zawsze zaczyna siĊ od ukoĞnika (ale nigdy na nim siĊ nie koĔ-
czy!), chyba Īe aplikacja zostanie umieszczona w katalogu gáównym serwera — wte-
dy zwracana wartoĞü to áaĔcuch pusty. Fragment ten jest wspólny dla wszystkich pli-
ków wchodzących w skáad tej aplikacji. Kolejny fragment adresu okreĞla ĞcieĪkĊ do
serwletu. W naszym przypadku jest to fragment:

/serwlety/info

PowyĪszy áaĔcuch znaków musi pasowaü do odpowiednich wzorców, zdefiniowanych
w deskryptorze wdroĪenia (pamiĊtasz znacznik

<url-pattern>

z poprzedniego roz-

dziaáu?). Zasady okreĞlania odpowiednich ĞcieĪek do serwletów omówimy w nastĊp-
nym rozdziale; na razie wystarczy Ci informacja, Īe ten fragment adresu umoĪliwia
jednoznaczne zidentyfikowanie serwletu.

Ostatni fragment ĞcieĪki (

/235/

) zostanie zwrócony przez metodĊ

getPathInfo()

. Do-

káadnie rzecz biorąc, metoda

getPathInfo()

zwraca fragment adresu URL od ĞcieĪki

serwletu do początku áaĔcucha parametrów (czyli do znaku zapytania). Oznacza to,
Īe nawet doáączenie parametrów, tak jak w poniĪszym przykáadzie, nie zmieni warto-
Ğci ĞcieĪki.

http://localhost:8080/MojaAplikacja/serwlety/info/235?param=1

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

29

Przesyäanie odpowiedzi

Po przeanalizowaniu wszystkich moĪliwych atrybutów Īądania musisz odesáaü klien-
towi odpowiedĨ. Do tego celu sáuĪy obiekt interfejsu

HttpServletResponse

. W jego

przypadku otrzymujemy nieco mniejszy zestaw metod, jednak nie oznacza to wcale
mniejszych moĪliwoĞci. Przede wszystkim musimy okreĞliü, jakie operacje chcemy
wykonywaü w związku z przesyáaniem odpowiedzi do klienta:



przesáanie odpowiedzi w postaci danych tekstowych lub binarnych,



utworzenie i przesáanie ciasteczek,



dodanie do odpowiedzi dowolnych nagáówków,



przekierowanie Īądania lub przesáanie kodu báĊdu.

Transmisja danych

ChociaĪ technologie internetowe mają swoją specyfikĊ, nie zapominajmy, Īe Īyjemy
w Ğwiecie Javy. Z tego wzglĊdu operacje zarówno odczytu, jak i zapisu wiąĪą siĊ
z wykorzystaniem strumieni i/lub obiektów klas

Reader

/

Writer

. Nie inaczej jest w tym

przypadku: zanim przeĞlemy jakiekolwiek dane, musimy uzyskaü odpowiednie obiek-
ty zapisujące:

 ServletOutputStream getOutputStream()

— zwraca strumieĔ zapisu

dla danych binarnych

 PrintWriter getWriter()

— zwraca obiekt zapisujący dla danych tekstowych.

W przypadku danych binarnych moĪemy skorzystaü z obiektu klasy

ServletOutput

´Stream

. Jest to zwykáy strumieĔ zapisu, rozszerzony o moĪliwoĞü zapisywania do-

wolnych danych typów prymitywnych, a takĪe áaĔcuchów znaków (za pomocą metod

print()

i

println()

). Z tej klasy naleĪy korzystaü w przypadku przesyáania plików —

jeĞli serwer musi w dynamiczny sposób wygenerowaü treĞü takiego pliku.

Znacznie czĊĞciej przyjdzie Ci jednak korzystaü z danych tekstowych. W tym przypad-
ku zazwyczaj bĊdziesz korzystaü z obiektu klasy

PrintWriter

i jego metody

println()

.

Nagäówki i ciasteczka

O ile w przypadku Īądania mamy do czynienia z odczytem nagáówków i ciasteczek
przesáanych przez klienta, o tyle w przypadku odpowiedzi wystĊpuje proces odwrot-
ny. Aby dodaü ciasteczko, wystarczy skorzystaü z metody

addCookie()

:

void addCookie(Cookie c)

WiĊcej na temat ciasteczek w osobnym podrozdziale. W przypadku nagáówków sytu-
acja jest nieco bardziej skomplikowana — do dyspozycji mamy dwie metody (wraz
z odpowiednikami dla liczb i dat):

void addHeader(String nazwa, String wartoħè)
void setHeader(String nazwa, String wartoħè)

background image

30

CzöĈè I i Podstawy

Na czym polega róĪnica? OtóĪ metoda

addHeader()

doda podaną wartoĞü do juĪ istnie-

jącej zawartoĞci nagáówka, natomiast metoda

setHeader()

zastąpi wartoĞü, jeĞli tako-

wa juĪ istnieje. Tak samo dziaáają bliĨniacze metody

addIntHeader()

,

addDateHeader()

,

setIntHeader()

i

setDateHeader()

.

Kody odpowiedzi, bäödy i przekierowania

Do obowiązków odpowiedzi HTTP naleĪy takĪe przekazywanie kodów odpowiedzi,
jeĞli chcemy zaznaczyü, Īe odpowiedĨ nie zostanie zakoĔczona w zwykáy sposób. Aby
przekazaü kod odpowiedzi, korzystamy z metody

setStatus()

:

void setStatus(int kod)

W ten sposób przekazujemy kody, które nie okreĞlają sytuacji problematycznych.
W przypadku báĊdów (np. 404 — brak zasobu) zaleca siĊ zdecydowanie wykorzysty-
wanie metody

sendError()

:

void sendError(int kod)
void sendError(int kod, String komunikat)

Jak widaü, istnieje moĪliwoĞü przesáania dodatkowej informacji na temat samego báĊ-
du. Ostatnią funkcjonalnoĞü związaną z kodami odpowiedzi stanowi przekierowanie.
ChociaĪ z technicznego punktu widzenia przekierowanie jest teĪ rodzajem kodu od-
powiedzi, do przekierowania wykorzystuje siĊ oddzielną metodĊ:

void sendRedirect(String adres)

Korzystając z metod

sendError()

i

sendRedirect()

, naleĪy pamiĊtaü o subtelnych

kwestiach związanych z fizycznym przesyáaniem danych do klienta. Przesyáanie ko-
munikatów o báĊdach lub przekierowaĔ wiąĪe siĊ z doĞü brutalną ingerencją w proces
przesyáania odpowiedzi. Proces ten jest natychmiast przerywany, a klient otrzymuje
odpowiedĨ z wybranym kodem odpowiedzi. Co jednak stanie siĊ, gdy zdąĪymy wy-
sáaü do klienta jakieĞ dane?

OdpowiedĨ jest prosta — nastąpi báąd. Po wysáaniu danych nie moĪesz ingerowaü
w treĞü nagáówków, przez co nie moĪesz ustawiü kodu odpowiedzi, a co za tym idzie
takĪe przekierowania. Czy oznacza to, Īe musisz uwaĪaü, gdzie wywoáujesz metodĊ

println()

obiektu

PrintWriter

? Na szczĊĞcie nie do koĔca.

DomyĞlnym zachowaniem obiektu w przypadku odpowiedzi jest zapisywanie danych
do bufora. Oznacza to, Īe dane zostaną wysáane po zakoĔczeniu metody lub w przy-
padku wywoáania metody

flush()

tego obiektu. Co za tym idzie, poniĪsza konstruk-

cja (wewnątrz metody

doGet()

) nie spowoduje wygenerowania báĊdu:

PrintWriter out = response.getWriter();
out.println("test");
response.sendRedirect("url/do/innego/serwletu");

JeĞli przed wywoáaniem metody

sendRedirect()

wywoáasz metodĊ

out.flush()

, wte-

dy báąd nastąpi. Zazwyczaj jednak takie wywoáanie jest pomijane, dziĊki czemu pro-
blem wystĊpuje stosunkowo rzadko.

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

31

Om nom nom, czyli ciasteczka w peänej krasie

Twórcy aplikacji webowych, podobnie jak Ciasteczkowy Potwór, mają szczególny
sentyment do ciasteczek (ang. cookies). Są to niewielkie pliki przechowywane na kom-
puterach uĪytkowników aplikacji webowych, dziĊki czemu jesteĞmy w stanie zapamiĊ-
tywaü ich preferencje, loginy i hasáa itd. Metody operujące na ciasteczkach poznaliĞmy
w poprzednim podrozdziale, ale teraz zaprezentujemy ich dziaáanie w praktycznym
przykáadzie (listing 3.1):

Listing 3.1. Przykáad obsáugi ciasteczek

protected void processRequest(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
Cookie lastVisit = null;
for (Cookie c : request.getCookies())
if (c.getName().equals("obecnosc")) {
lastVisit = c;
break;
}
if (lastVisit != null)
out.println("Twoja ostatnia wizyta na stronie miađa miejsce w dniu " +
lastVisit.getValue());
else
out.println("Do tej pory nie odwiedziđeħ/aħ naszej strony. Wstydļ siú!");
lastVisit = new Cookie("obecnosc", new Date().toString());
response.addCookie(lastVisit);
} finally {
out.close();
}
}

Zadaniem powyĪszego serwletu jest przechowywanie informacji o dacie ostatniej wi-
zyty na stronie i wyĞwietlanie jej. W przypadku braku ciasteczka z datą (co jest równo-
znaczne z pierwszymi odwiedzinami na tej stronie, przynajmniej od czasu wyczysz-
czenia ciasteczek w przeglądarce) wyĞwietlamy inną informacjĊ. Warto zwróciü uwagĊ
na dwie kwestie. Po pierwsze, jeĞli chcemy odczytaü juĪ istniejące ciasteczka — ko-
rzystamy z metody

getCookies()

znajdującej siĊ w obiekcie

request

. JeĞli chcemy

dodaü ciasteczko — korzystamy z obiektu

response

. Nigdy odwrotnie! Sprawa druga,

znacznie bardziej przykra — powyĪszy sposób dostĊpu do ciasteczek uĪytkownika
(pĊtla

for..in

) stanowi jedyną metodĊ znajdywania ciasteczek o okreĞlonej nazwie.

W przypadku tworzenia prawdziwych aplikacji trzeba zdefiniowaü osobną metodĊ do
wyszukiwania ciasteczek.

Sesje — nie tylko dla studentów

Obsáuga sesji jest kolejnym nieodáącznym elementem niemal wszystkich aplikacji we-
bowych. W przypadku JEE interakcje z sesją moĪemy prowadziü na róĪne sposoby,

background image

32

CzöĈè I i Podstawy

takĪe za pomocą poznanych juĪ klas. W tym rozdziale poznamy sposób na dostĊp do
sesji za pomocą obiektu klasy

HttpServletRequest

. Kluczową rolĊ odgrywa metoda

getSession()

, wystĊpująca w dwóch wariantach:

HttpSession getSession()
HttpSession getSession(boolean czyTworzyc)

Na wstĊpie zaznaczĊ, Īe pierwszy wariant tej metody jest równowaĪny drugiemu wy-
woáanemu z parametrem

true

. Drugi wariant postĊpuje róĪnie w zaleĪnoĞci od prze-

kazanej wartoĞci logicznej:



JeĞli parametr ma wartoĞü

true

, metoda zwraca obiekt sesji lub tworzy nowy,

jeĞli ten nie istnieje.



JeĞli parametr ma wartoĞü

false

, metoda zwraca obiekt sesji lub

null

, jeĞli ten

nie istnieje.

Jak widaü, wartoĞü

true

naleĪy przekazaü, jeĞli chcesz po prostu uzyskaü dostĊp do

sesji. WartoĞü

false

stosuje siĊ, gdy chcesz sprawdziü, czy sesja istnieje. MoĪna sko-

rzystaü z tego mechanizmu, aby sprawdziü, czy dane Īądanie jest pierwszym Īądaniem
uĪytkownika w danej sesji. Mechanizm ten jest realizowany w poniĪszym przykáadzie
z listingu 3.2:

Listing 3.2. Przykáad wykorzystania sesji

protected void processRequest(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
if (request.getSession(false)==null)
{
out.println("Witaj na stronie po raz pierwszy!");
request.getSession();
}
else
out.println("Witaj na stronie po raz kolejny!");
} finally {
out.close();
}
}

JeĞli po utworzeniu sesji chcesz sprawdziü, czy sesja zostaáa dopiero co utworzona,
skorzystaj z metody

isNew()

:

 boolean isNew()

— zwraca

true

, jeĞli obiekt sesji zostaá utworzony podczas

tego Īądania.

Korzystanie z obiektu sesji

Podstawowa funkcjonalnoĞü obiektu sesji sprowadza siĊ do dwóch metod:

 Object getAttribute(String nazwa)

— zwraca atrybut sesji o podanej nazwie.

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

33

 void setAttribute(String nazwa, Object wartoħè)

— dodaje obiekt

do sesji, przypisując mu podany klucz (nazwĊ). JeĞli jakiĞ obiekt o takiej
samej nazwie juĪ istniaá, zostanie on zastąpiony.

Wiemy juĪ, jak utworzyü sesjĊ, wiemy teĪ, jak z niej skorzystaü. Pozostaáo nam omó-
wienie, jakie są warunki zakoĔczenia sesji. MoĪe ono nastąpiü w wyniku kilku róĪnych
sytuacji:



rĊczne zakoĔczenie sesji przez programistĊ,



upáyniĊcie czasu Īycia sesji,



zamkniĊcie okna przeglądarki przez uĪytkownika.

Ostatni przypadek, jest rzecz jasna, najprostszy — nie wymaga on naszej ingerencji.
RĊczne zakoĔczenie sesji wiąĪe siĊ z wywoáaniem nastĊpującej metody:

 void invalidate()

— koĔczy sesjĊ.

Najciekawiej sytuacja wygląda w przypadku okreĞlania terminu waĪnoĞci sesji. Istnie-
ją bowiem dwie moĪliwoĞci okreĞlenia tej wartoĞci — pierwsza z nich jest stosowana
w pliku konfiguracyjnym web.xml:

<web-app>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
</web-app>

Podana wartoĞü okreĞla czas waĪnoĞci sesji w minutach. Obowiązuje on dla wszyst-
kich sesji, chyba Īe skorzystasz z moĪliwoĞci okreĞlenia czasu Īycia sesji w kodzie:

 void setMaxInactiveInterval(int czas)

— okreĞla czas Īycia sesji

w sekundach. Podanie wartoĞci 0 i ujemnych powoduje, Īe sesja nigdy
nie wygasa (do jej zakoĔczenia jest wiĊc konieczne wywoáanie metody

invalidate()

lub zamkniĊcie okna przeglądarki przez uĪytkownika).

Konfiguracja w kodzie Javy
— mo

Ĕna tego uniknñè

Podczas tworzenia wiĊkszoĞci aplikacji programiĞci muszą zmierzyü siĊ z problemem
obsáugi róĪnego rodzaju ustawieĔ wpáywających na dziaáanie aplikacji. Problemem
staje siĊ lokalizacja tych ustawieĔ. Z jednej strony nikt nie chce utrudniaü sobie Īycia
— w koĔcu nie ma nic prostszego, niĪ wczytaü wartoĞü umieszczoną w staáej/zmiennej.
Z drugiej jednak strony zmiana takich ustawieĔ wymagaáaby rekompilacji caáego pro-
jektu, w najlepszym przypadku — jednej biblioteki.

Z tego wzglĊdu powszechnym standardem staáo siĊ umieszczanie róĪnego rodzaju
ustawieĔ w zewnĊtrznych Ĩródáach danych — plikach binarnych, tekstowych, XML;

background image

34

CzöĈè I i Podstawy

rzadziej w bazach danych. W przypadku aplikacji webowych JEE miejscem takim
jest deskryptor wdroĪenia — plik web.xml. Poza licznymi ustawieniami związanymi
z funkcjonowaniem aplikacji jako takiej (czĊĞü z nich juĪ poznaáeĞ), w pliku web.xml
moĪesz takĪe zdefiniowaü parametry dla poszczególnych serwletów, a takĪe caáej apli-
kacji webowej.

Parametry serwletów

Parametry serwletów moĪesz okreĞlaü za pomocą znacznika

<init-param>

w nastĊpu-

jący sposób:

<servlet>
<servlet-name>ParameterServlet</servlet-name>
<servlet-class>pl.helion.jeeweb.ParameterServlet</servlet-class>
<init-param>
<param-name>autor</param-name>
<param-value>Krzysztof Rychlicki-Kicior</param-value>
</init-param>
</servlet>

Po dwóch znanych juĪ znacznikach (

servlet-name

i

servlet-class

) nastĊpuje dowol-

na liczba znaczników

init-param

. KaĪdy taki znacznik zawiera dwa kolejne, okreĞla-

jące nazwĊ i wartoĞü parametru. Parametry serwletów moĪna teĪ dodawaü w Ğrodowi-
sku Netbeans, podczas tworzenia serwletu (w ostatnim kroku kreatora).

Pierwszy parametr utworzony, najwyĪsza pora, aby odczytaü go we wnĊtrzu serwletu.
Do zarządzania parametrami serwletów sáuĪy interfejs

ServletConfig

, który jest im-

plementowany przez znane nam klasy

GenericServlet

i

HttpServlet

. Dwie metody

tego interfejsu, które interesują nas w tej chwili najbardziej, to:

 String getInitParameter(String nazwa)

— zwraca wartoĞü parametru

o podanej nazwie.

 String[] getInitParameterNames()

— zwraca wszystkie nazwy parametrów

danego serwletu.

protected void processRequest(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("Autorem serwletu jest " + this.getInitParameter("autor"));
} finally {
out.close();
}
}

DziĊki umieszczeniu konfiguracji w pliku XML odnieĞliĞmy wymierną korzyĞü. Zmia-
na wartoĞci w pliku XML nie wymaga rekompilacji kodów Ĩródáowych, a jedynie prze-
áadowania aplikacji (w przypadku Tomcata istnieje takĪe opcja automatycznego wy-
krywania zmian i przeáadowywania aplikacji).

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

35

Interfejs

ServletConfig

poza dwoma poznanymi metodami udostĊpnia metodĊ

get

´ServletName()

, zwracającą nazwĊ serwletu, a takĪe metodĊ

getServletContext()

.

Zwraca ona (a jakĪeby inaczej) kontekst serwletów — jeden z najwaĪniejszych obiek-
tów w caáym Ğwiecie aplikacji webowych JEE.

Kontekst serwletów

Kontekst serwletów to obiekt, który sáuĪy do komunikacji serwletów z kontenerem.
DziĊki niemu moĪesz dynamicznie dodawaü serwlety do aplikacji, uzyskiwaü dostĊp
do zasobów znajdujących siĊ w jej obrĊbie, zapisywaü logi do serwerowego dzienni-
ka, a co najwaĪniejsze z obecnego punktu widzenia — moĪesz korzystaü z parametrów
aplikacji webowej (kontekstu). Od parametrów serwletów róĪni je zasiĊg oddziaáywa-
nia. KaĪdy parametr kontekstu jest widoczny we wszystkich serwletach i innych pli-
kach. Parametry serwletu są okreĞlane w podobny sposób jak w przypadku serwletów:

<web-app>
<context-param>
<param-name>tytul </param-name>
<param-value>Java EE 6. Tworzenie aplikacji webowych</param-value>
</context-param>

</web-app>

RównieĪ sposób wykorzystywania parametrów kontekstu przypomina ten znany
z serwletów:

try {
out.println("Wszystkie przykđady pochodzæ z ksiæľki " +
this.getServletContext().getInitParameter("tytul"));
} finally {
out.close();
}

Jedyną róĪnicĊ stanowi odwoáanie siĊ do obiektu kontekstu. Reszta pozostaje bez zmian
— nawet nazwa metody. CiekawostkĊ stanowi metoda wprowadzona w specyfikacji
Java Servlets 3.0. OtóĪ aĪ do momentu wprowadzenia tej specyfikacji parametry, za-
równo serwletów, jak i kontekstu, byáy wartoĞciami tylko do odczytu. Jedyną moĪli-
woĞcią zmiany parametrów byáa edycja pliku web.xml. W wersji JavaServlet 3.0 API
pojawiáa siĊ jednak innowacja — moĪliwoĞü dynamicznego ustawiania parametrów
kontekstu za pomocą metody

setInitParameter()

. Wynika to z wprowadzenia duĪej

elastycznoĞci — klasa

ServletContext

w wersji 3.0 uzyskaáa wiele metod, takich jak

addServlet()

, czy

addFilter()

, które umoĪliwiają dynamiczne dodawanie róĪnych

skáadników aplikacji, do tej pory deklarowanych jedynie w pliku web.xml. Nie naleĪy
jednak naduĪywaü tej metody.

Kontekst serwletów pojawi siĊ ponownie juĪ niebawem, tymczasem nadszedá czas,
aby zmierzyü siĊ z przeciwnikiem o wiele waĪniejszym od parametrów — mowa
o atrybutach.

background image

36

CzöĈè I i Podstawy

Trzech muszkieterów?

Parametry, czy to serwletów, czy to aplikacji, mają swoje zastosowania i bywają nie-
zwykle przydatne. Mimo to gáównym Ğrodkiem komunikacji miĊdzy serwletami, kon-
tenerem, sesją, uĪytkownikiem i obiektem Īądania — czyli z grubsza miĊdzy wszyst-
kimi elementami aplikacji — są atrybuty. Z technicznego punktu widzenia miĊdzy
parametrami i atrybutami wystĊpują dwie zasadnicze róĪnice:



W przypadku parametrów zarówno klucz, jak i wartoĞü są áaĔcuchami
znaków, zaĞ w przypadku atrybutów — klucz jest áaĔcuchem, wartoĞü
moĪe byü obiektem.



Parametry z zaáoĪenia są tylko do odczytu (choü w Ğwietle ostatniej wersji
specyfikacji wygląda to inaczej…), natomiast atrybuty są przeznaczone
zarówno do odczytu, jak i do zapisu.

Niezwykáe znaczenie ma takĪe wprowadzenie zasiĊgu atrybutów. Atrybut dodany w za-
siĊgu Īądania (request) nie bĊdzie widoczny w innych zasiĊgach. Tabela 3.1 przedsta-
wia zestawienie parametrów i atrybutów w poszczególnych zakresach.

Tabela 3.1. MoĪliwoĞci zapisywania i odczytywania parametrów i atrybutów w poszczególnych

zakresach

Parametry

Atrybuty

Zakres

Zapis

Odczyt

Zapis

Odczyt

ĩądanie

nie

tak

tak

tak

Serwlet

nie

tak

brak

brak

Sesja

brak

brak

tak

tak

Kontekst aplikacji

tak (od wersji 3.0)

tak

tak

tak

Na podstawie powyĪszej tabeli wydaü wyraĨnie, Īe parametry peánią jedynie funkcjĊ
ustawieĔ, opcji konfiguracyjnych, które uáatwiają zmianĊ w dziaáaniu aplikacji bez
koniecznoĞci ponownej rekompilacji kodu. Atrybuty natomiast mają zastosowanie
o wiele szersze — sáuĪą do wymiany informacji pomiĊdzy poszczególnymi elementa-
mi aplikacji.

W dalszej czĊĞci rozdziaáu skupimy siĊ tylko na atrybutach. Ich ogromna przydatnoĞü
ma bowiem pewne ograniczenia. Jedno z nich jest związane z najwaĪniejszą chyba ce-
chą odróĪniającą aplikacje webowe od aplikacji typu standalone — koniecznoĞü jed-
noczesnej obsáugi wielu uĪytkowników.

Atrybuty a mnogoĈè Ĕñdaþ

Jedna aplikacja webowa moĪe byü uĪywana nawet przez setki czy tysiące uĪytkowni-
ków jednoczeĞnie. KaĪde Īądanie (HTTP request) jest obsáugiwane przez kontener
w osobnym wątku. Istotną kwestią jest wiĊc zapewnienie integralnoĞci operacji wyko-

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

37

nywanych przez kaĪdego z nich — nie moĪe byü tak, Īe operacje jednego uĪytkowni-
ka wpáyną na efekt operacji innego.

W przypadku parametrów problem ten raczej nie wystĊpuje. Co prawda, w wersji 3.0
pojawiáa siĊ moĪliwoĞü modyfikowania parametrów kontekstu aplikacji, jednak moĪli-
woĞü ta powinna byü uĪywana w bardzo sporadycznych sytuacjach, gdy obsáuga wielu
uĪytkowników nie powinna sprawiaü problemów (np. z powodu wywoáywania takiego
kodu przez superadministratora witryny). JeĞli jednak zabezpieczenie jest konieczne,
moĪna zrealizowaü je w sposób analogiczny do tego, który zaprezentujĊ za chwilĊ.

Zdecydowanie bardziej skomplikowana sytuacja wystĊpuje w przypadku atrybutów.
Wszystkie trzy przypadki omówiĊ w kolejnych podrozdziaáach.

Atrybuty Ĕñdania

W przypadku atrybutów Īądania sytuacja jest stosunkowo prosta. ĩądanie jest realizo-
wane przez jednego uĪytkownika; w dodatku pojedyncze Īądanie nie wiąĪe siĊ w Īa-
den sposób z innymi Īądaniami (nawet tego samego uĪytkownika), dlatego problem
jednoczesnego dostĊpu przez wielu uĪytkowników nie wystĊpuje. Pojawia siĊ jednak
inne pytanie — skoro obiekt Īądania nie wchodzi w interakcje z innymi Īądaniami, po
co miaáby korzystaü z atrybutów?

Takie rozwiązanie wynika ze stosowanych w praktyce mechanizmów obsáugi stron.
Serwlety same w sobie rzadko generują treĞü — na ogóá wykonują one róĪnorodne
operacje (np. pobranie danych z bazy, realizacja logiki biznesowej — choü w wiĊk-
szych aplikacjach i te zadania są delegowane), a nastĊpnie przekazują sterowanie do
pliku JSP. W takiej sytuacji konieczne jest przekazanie informacji miĊdzy serwletem
a plikiem JSP. Voilà! — znaleĨliĞmy zastosowanie atrybutów Īądania. Dokáadne wy-
jaĞnienie i przykáady poznasz w rozdziale poĞwiĊconym JSP.

Atrybuty sesji

W nieco gorszej sytuacji są atrybuty sesji. Wiemy juĪ, Īe jedna sesja jest powiązana
z konkretnym uĪytkownikiem. Teoretycznie nie powinno wiĊc byü problemów. Ale
uĪytkownicy bywają okrutni — wyobraĨ sobie, co mogáoby siĊ staü, gdyby uĪytkow-
nik uruchomiá Twoją aplikacjĊ webową w dwóch zakáadkach i próbowaá jednoczeĞnie
áadowaü róĪne (lub te same) serwlety?

OdpowiedĨ jest prosta: mogáoby dojĞü do jednoczesnego dostĊpu do sesji. Odczyt da-
nych nie stanowiáby problemu, ale atrybuty sesyjne mogą byü przecieĪ równieĪ zapi-
sywane. Taka sytuacja to potencjalny problem. Jak wiĊc mu zaradziü?

Powiem krótko: naleĪy skorzystaü ze standardowego mechanizmu Javy, chroniącego
dane przed zapisem przez wiele wątków jednoczeĞnie — synchronizacji. Teraz musi-
my okreĞliü, dostĊp do czego dokáadnie chcemy synchronizowaü.

Na początek odrzuümy obiekt Īądania (klasy

HttpServletRequest

). Jest to obiekt zwią-

zany tylko z jednym, konkretnym Īądaniem, wiĊc zablokowanie dostĊpu do niego nie
wpáynĊáoby na inne obiekty ĪądaĔ — nadal wszystkie one mogáyby korzystaü bez

background image

38

CzöĈè I i Podstawy

skrĊpowania z sesji. Nie ma sensu równieĪ blokada obiektu serwletu — dostĊp do se-
sji mają róĪne serwlety, wiĊc zablokowanie jednego z nich nie powstrzyma innych od
zapisu do sesji. Jedynym sensownym rozwiązaniem pozostaje zablokowanie obiektu
sesji, do którego uzyskujemy dostĊp za pomocą obiektu Īądania. PoniĪszy kod, wsta-
wiony we wszystkich serwletach, pozwoli na zliczenie wszystkich wywoáaĔ serwle-
tów, które miaáy miejsce w aplikacji webowej dla danego uĪytkownika:

HttpSession sesja = request.getSession();
synchronized(sesja) {
if (sesja.isNew())
sesja.setAttribute("licznik", 1);
else
{
int licznik = Integer.parseInt(sesja.getAttribute("licznik").toString());
sesja.setAttribute("licznik", licznik + 1);
}
}

W ten sposób, gdy jeden serwlet wejdzie w blok synchronizowany, uzyskujemy gwa-
rancjĊ, Īe Īaden inny serwlet w tym momencie dostĊpu do sesji nie uzyska. Wszystkie
inne serwlety bĊdą musiaáy czekaü, aĪ pierwszy serwlet zwolni blokadĊ.

Atrybuty kontekstu serwletów

NajwiĊksze niebezpieczeĔstwo niesie za sobą korzystanie z atrybutów naleĪących do
kontekstu aplikacji. KaĪdy taki atrybut moĪe byü odczytany i zmodyfikowany w do-
wolnym niemal miejscu aplikacji. Z tego wzglĊdu kaĪda próba korzystania z atrybu-
tów (zwáaszcza zapisu) powinna byü synchronizowana.

Zasada dziaáania jest taka sama, jak w przypadku sesji. W tym przypadku musimy jednak
synchronizowaü obiekt kontekstu. Kod synchronizujący przedstawia siĊ nastĊpująco:

ServletContext sc = this.getServletContext();
synchronized(sc)
{
Object licznik = sc.getAttribute("licznik");
if (licznik == null)
sc.setAttribute("licznik", 1);
else
{
licznik = sc.getAttribute("licznik");
sc.setAttribute("licznik", Integer.parseInt(licznik.toString()) + 1);
}
}

PowyĪszy kod realizuje funkcjonalnoĞü podobną do przykáadu z sesją — tym razem
zliczamy jednak wszystkie wywoáania serwletów wykonane przez wszystkich uĪyt-
kowników.

Z obiektami ĪądaĔ, sesji i kontekstu, jak równieĪ z ich atrybutami, wiąĪą siĊ waĪne
klasy — sáuchaczy zdarzeĔ. Choü istnieje moĪliwoĞü tworzenia caáych aplikacji we-
bowych bez ĞwiadomoĞci istnienia tych klas, zdarzają siĊ sytuacje, w których znajo-
moĞü tego typu mechanizmów jest niezbĊdna.

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

39

S

äuchowisko

Sáuchacze zdarzeĔ to obiekty spotykane w Javie niezwykle czĊsto. Początkujący pro-
gramiĞci Javy spotykają siĊ z nimi np. podczas tworzenia prostych aplikacji graficz-
nych. Sáuchacz zdarzeĔ powiązany z przyciskiem pozwalaá na wykonanie dowolnego
kodu np. po jego klikniĊciu. PojĊcie sáuchacza zdarzeĔ nie ogranicza siĊ oczywiĞcie
do tworzenia aplikacji z graficznym interfejsem — równieĪ aplikacje webowe dają
sáuchaczom zdarzeĔ spore pole do popisu.

W poniĪszych podrozdziaáach przedstawiĊ interfejsy sáuchaczy zdarzeĔ przeznaczone
do uĪycia w aplikacjach webowych. Nie jest to moĪe najciekawszy fragment niniej-
szej ksiąĪki, ale prĊdzej czy póĨniej znajdziesz siĊ w sytuacji, w której bĊdziesz mu-
siaá skorzystaü z opisanych w nastĊpnych akapitach mechanizmów.

ServletContextListener

Jest to najrzadziej chyba wykorzystywany sáuchacz zdarzeĔ. Zawiera dwie metody:

contextInitialized()

i

contextDestroyed()

, które są wywoáywane w momencie utwo-

rzenia/usuniĊcia kontekstu aplikacji, czyli — w momencie startu i zakoĔczenia aplika-
cji. Obydwie metody przyjmują parametr typu

ServletContextEvent

— umoĪliwia on

pobranie kontekstu aplikacji za pomocą metody

getServletContext()

.

ServletContextAttributeListener

Drugim sáuchaczem zdarzeĔ związanym z kontekstem aplikacji jest sáuchacz obser-
wujący kolekcjĊ atrybutów kontekstu. Reaguje on na dodawanie (metoda

attribute

´Added()

), usuwanie (

attributeRemoved()

) i zamianĊ (

attributeReplaced()

) atrybu-

tów. Wszystkie trzy metody przyjmują jeden parametr typu

ServletContextAttribute

´Event

— umoĪliwia on pobranie nazwy modyfikowanego atrybutu (

getName()

), jego

wartoĞci (

getValue()

).

ServletRequestAttributeListener
i ServletRequestListener

Obydwa interfejsy peánią analogiczne funkcje, co ich „kontekstowi” koledzy — na-
wet nazwy metod są podobne (w przypadku pierwszego interfejsu — identyczne,
w przypadku drugiego —

requestInitialized()

i

requestDestroyed()

). Jedyną real-

ną zmianą jest wprowadzenie dodatkowej funkcjonalnoĞci do klas argumentów zdarzeĔ

ServletRequestAttributeEvent

i

ServletRequestEvent

. UdostĊpniają one metodĊ

getServletRequest()

. Pozwala ona na skorzystanie z obiektu Īądania, którego zda-

rzenia dotyczą.

background image

40

CzöĈè I i Podstawy

HttpSessionAtributteListener
i HttpSessionListener

RównieĪ sáuchacze zdarzeĔ powiązani z sesjami zostaáy utworzone zgodnie z omówio-
nymi powyĪej zasadami. Sáuchacz

HttpSessionListener

jest wykorzystywany przy

tworzeniu (metoda

sessionCreated()

) i koĔczeniu sesji (

sessionDestroyed()

). Prze-

kazywany argument — obiekt klasy

HttpSessionEvent

— udostĊpnia metodĊ

getSes-

sion()

, która daje dostĊp do utworzonej (zakoĔczonej) sesji. W przypadku interfejsu

HttpSessionAttributeListener

mamy do dyspozycji te same trzy metody, co w po-

przednich przypadkach. Typ zdarzenia to

HttpSessionBindingEvent

. Jego moĪliwoĞci

sprowadzają siĊ do pobrania obiektu sesji i nazwy/wartoĞci dodawanego/usuwanego/
zmienianego atrybutu.

HttpSessionBindingListener

Nareszcie coĞ ciekawego! Tytuáowy interfejs odbiega nieco od schematu, z jakim mie-
liĞmy do czynienia przez ostatnie trzy podrozdziaáy. Wszystkie trzy interfejsy z czáo-
nem

AttributeListener

w nazwie odpowiadaáy za informowanie o zmianach zacho-

dzących w kolekcji atrybutów. Dla odmiany interfejs

HttpSessionBindingListener

powinien byü implementowany przez klasy, których obiekty bĊdą umieszczane w se-
sji! JeĞli wiĊc tworzysz wáasne klasy do przechowywania danych, które w momencie
zapisu do sesji powinny byü w jakiĞ sposób przetworzone, powinieneĞ skorzystaü z tego
interfejsu. Metody tego interfejsu to

valueBound()

i

valueUnbound()

, wywoáywane od-

powiednio w momencie doáączenia obiektu do sesji lub jego usuniĊcia. Klasa argu-
mentu zdarzeĔ to znana z poprzedniego akapitu

HttpSessionBindingEvent

.

Sesja + wiele JVM = HttpSessionActivationListener

Java EE to technologia uniwersalna, która moĪe byü z powodzeniem stosowana w roz-
budowanych aplikacjach webowych i biznesowych. Jednym z waĪnych aspektów two-
rzenia takich aplikacji jest skalowalnoĞü — moĪliwoĞü poprawnego i wydajnego dziaáa-
nia aplikacji w dowolnych warunkach (niewielkiego, jak i bardzo duĪego obciąĪenia),
bez koniecznoĞci zmiany samej aplikacji. Bardzo czĊsto, w celu poprawy wydajnoĞci,
ta sama aplikacja jest instalowana na wielu komputerach poáączonych w sieü, a spe-
cjalny serwer, bĊdący bramą do Ğwiata zewnĊtrznego (czyli do klientów), kieruje „ru-
chem” i przydziela poszczególne Īądania do tych komputerów, które w danym mo-
mencie są najmniej obciąĪone. Taka technika nosi nazwĊ równowaĪenia obciąĪenia
(ang. load balancing).

Nie bĊdziemy zagáĊbiaü siĊ teraz w szczegóáy tej techniki; w niniejszej ksiąĪce bĊdzie
nas interesowaü co najwyĪej wpáyw tej techniki na kod aplikacji lub informacje za-
warte w deskryptorze wdroĪenia. W tym podrozdziale zajmiemy siĊ sáuchaczem zda-
rzeĔ, który jest związany z dwoma istotnymi zagadnieniami: obsáugą sesji i równowa-
Īeniem obciąĪenia.

background image

Rozdziaä 3. i Serwlet — na dobry poczñtek

41

Gdy uĪytkownik tworzy obiekt sesji, jest on zapisywany (np. w postaci pliku) na kom-
puterze, który obsáugiwaá w danej chwili Īądanie. NastĊpne Īądanie uĪytkownika mo-
Īe jednak byü przydzielone do zupeánie innego komputera wewnątrz sieci — dlatego
konieczne jest wprowadzenie mechanizmu, który przeniesie obiekt sesji z pierwszego
komputera na drugi.

Na szczĊĞcie mechanizm ten jest automatyczny. Jedynym (opcjonalnym) zadaniem
programisty jest wykonanie operacji przed przeniesieniem sesji z komputera pierwot-
nego i po przeniesieniu sesji na komputer docelowy. SáuĪą do tego celu metody:

 void sessionWillPassivate(HttpSessionEvent hse)

— metoda wywoáywana

tuĪ przed przesáaniem sesji do innego komputera;

 void sessionDidActivate(HttpSessionEvent hse)

— metoda wywoáywana

tuĪ po otrzymaniu sesji od pierwszego komputera.

Filtry

Do tej pory wszystkie przykáady omawialiĞmy, korzystając z modelu obsáugi Īądania/
odpowiedzi. ĩądanie HTTP przesáane przez klienta powodowaáo utworzenie nowego
wątku, wykorzystującego obiekt odpowiedniego serwletu. Na podstawie metody Īą-
dania HTTP nastĊpowaá wybór odpowiedniej metody klasy

HttpServlet

(

doGet()

,

doPost()

itd.). Model ten moĪna jednak rozszerzyü o dodatkowe elementy — filtry.

Filtr umoĪliwia wykonywanie operacji w momencie nadejĞcia ĪądaĔ do serwletów
i wygenerowania przezeĔ odpowiedzi, przy czym nie ingeruje on w dziaáanie samego
serwletu. MoĪna zatem np. zapisaü w dzienniku datĊ kaĪdego Īądania, jego parametry,
a takĪe sprawdziü, jaka jest dáugoĞü odpowiedzi wygenerowanej przez serwlet.

W praktyce serwlety stosuje siĊ równieĪ do kontroli, a ewentualnie takĪe modyfikacji
obiektów Īądania i odpowiedzi. DziĊki filtrom moĪesz skompresowaü caáą treĞü od-
powiedzi, zanim zostanie przesáana ostatecznie do klienta. MoĪesz teĪ w uniwersalny
sposób odrzucaü Īądania, które nie speániają okreĞlonych warunków (np. wartoĞü
ustalonych parametrów). NajwiĊkszą zaletą filtrów jest moĪliwoĞü podáączenia ich
do dowolnej grupy serwletów — filtry są áączone z serwletami za pomocą znacznika

url-pattern

, dziaáającego analogicznie jak w przypadku serwletów. Jak widaü, doda-

nie jednego znacznika pozwala na wáączenie szyfrowania, kompresji lub kontroli do-
stĊpu dla caáej grupy serwletów.

Techniczny aspekt filtrów

Z technicznego punktu widzenia filtr jest klasą implementującą interfejs

javax.servlet.

Filter

. Interfejs ów skáada siĊ z trzech metod:

 void init(FilterConfig fc)

— metoda wywoáywana przy utworzeniu

filtru. Pozwala na uzyskanie obiektu ustawieĔ filtru — obiektu interfejsu

FilterConfig

.

background image

Czytaj dalej...

42

CzöĈè I i Podstawy

 void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain)

— metoda wywoáywana w momencie nadejĞcia Īądania.

Dokáadny opis w dalszej czĊĞci podrozdziaáu.

 void destroy()

— metoda wywoáywana przez serwer w momencie

zakoĔczenia dziaáania filtru.

NajwiĊksze znaczenie ma, rzecz jasna, metoda

doFilter()

. Typowy sposób jej wyko-

rzystania przedstawiam poniĪej:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
if (!req.isSecure())
((HttpServletResponse)res).sendError(HttpServletResponse.SC_RESPONSE);
chain.doFilter(req, res);
bool spakowany = false;
if (req.getParameter("format") != null &&
req.getParameter("format").equals("spakowany"))
spakowany = true;
if (spakowany) {
// pobierz treĞü odpowiedzi, spakuj ją, a nastĊpnie
// zapisz, korzystając z obiektu res.
}
}

TreĞü powyĪszej metody moĪna podzieliü na trzy czĊĞci. Na początku sprawdzamy,
czy dane Īądanie jest realizowane w trybie bezpiecznym, czyli z wykorzystaniem pro-
tokoáu SSL. JeĞli nie — odsyáamy uĪytkownikowi kod báĊdu 403 — forbidden (brak
uprawnieĔ do zrealizowania Īądania).

NajwaĪniejszym fragmentem metody jest wywoáanie

doFilter()

obiektu

chain

. ZbieĪ-

noĞü nazw w tej sytuacji jest przypadkowa (klasy

FilterChain

i

Filter

nie są ze sobą

w Īaden formalny sposób związane). Zadaniem interfejsu

FilterChain

jest zapewnie-

nie komunikacji miĊdzy filtrem (lub grupą filtrów) a serwletem. W zaleĪnoĞci od ko-
lejnoĞci deklaracji filtrów w deskryptorze wdroĪenia Īądanie HTTP przechodzi przez
kolejne filtry (dziĊki wywoáaniom metody

doFilter()

w kaĪdym filtrze), aĪ w koĔcu

dociera do serwletu. Po zakoĔczeniu obsáugi przez serwlet, sterowanie powraca do ko-
lejnych filtrów (w naszym przypadku od deklaracji zmiennej

spakowany

, aĪ do opusz-

czenia ostatniego filtru).

Konfiguracja filtrów w pliku web.xml

Samo utworzenie klas filtrów to za maáo. Musisz dodaü takĪe odpowiednie wpisy w pli-
ku web.xml. Zasada dziaáania filtrów przypomina tĊ znaną z serwletów, dlatego rów-
nieĪ informacje podawane w deskryptorze wdroĪenia powinny wydaü Ci siĊ znajome:

<filter>
<filter-name>Pierwszy filtr</filter-name>
<filter-class>pl.helion.jeeweb.Filtr<filter-class>
</filter>
<filter-mapping>
<filter-name>Pierwszy filtr</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


Wyszukiwarka

Podobne podstrony:
Java EE 6 Programowanie aplikacji WWW [PL]
informatyka j2me praktyczne projekty wydanie ii krzysztof rychlicki kicior ebook
informatyka java zadania z programowania z przykladowymi rozwiazaniami miroslaw j kubiak ebook
informatyka java ee 6 leksykon kieszonkowy arun gupta ebook
ebook Krzysztof Rychlicki Kicior J2ME Praktyczne projekty (j2mepp) helion onepress free ebook darm
informatyka jak zarabiac na aplikacjach i grach mobilnych piotr stalewski ebook
ARCHITEKTURA Bazodanowych aplikacji WWW, edukacja i nauka, Informatyka
informatyka programowanie aplikacji dla urzadzen mobilnych z systemem windows mobile jacek matulewsk
informatyka android flash zaawansowane programowanie aplikacji mobilnych stephen chin ebook
Eclipse Web Tools Platform Tworzenie aplikacji WWW w jezyku Java
informatyka cakephp 1 3 programowanie aplikacji receptury mariano iglesias ebook
informatyka javascript aplikacje www alex maccaw ebook
informatyka splatana siec przewodnik po bezpieczenstwie nowoczesnych aplikacji www michal zalewski e
informatyka tworzenie aplikacji dla windows od prostych programow do gier komputerowych pawel borkow
informatyka bezpieczne programowanie aplikacje hakeroodporne jacek ross ebook
informatyka programowanie aplikacji na iphone 4 poznaj platforme ios sdk3 od podstaw david mark eboo
informatyka java przygotowanie do programowania na platforme android jeff friesen ebook

więcej podobnych podstron