136 54 7MB
Polish Pages [595] Year 2002
O Autorach Jason Hunter jest starszym technologiem w firmie CollabNet (http://collab.net), firmie dostarczającej narzędzia i usługi dla współpracy Open Source. Oprócz bycia autorem ksiąŜki „Java Servlet — programowanie” jest takŜe redaktorem witryny Servlets.com, twórcą biblioteki com.oreilly.servlet, współpracownikiem projektu Apache Jakarta, który tworzy serwer Tomcat (od czasów, kiedy projekt był jeszcze wewnętrzną częścią firmy Sun), członkiem grupy ekspertów odpowiedzialnej za tworzenie API Servlet/JSP i JAXP oraz jest członkiem Komitetu Wykonawczego JCP nadzorującego platformę Javy, jako reprezentant Apache Software Foundation. Pisze równieŜ artykuły dla JavaWorld oraz przemawia na wielu konferencjach programistycznych i Open Source. W ostatnich czasach współtworzył bibliotekę Open Source JDOM (http://jdom.org), pozwalającą na optymalizację integracji Javy i XML oraz przewodzi grupie ekspertów odpowiedzialnej za tworzenie JDOM. Jason poprzednio pełnił funkcję głównego technologa w firmie K&A Software, specjalizującej się w treningach i konsultacjach związanych z Javą i działał jako wynajęty ekspert dla wielu przedsiębiorstw włączając w to Sun Microsystems. Jeszcze wcześniej pracował w Silicon Graphics, gdzie był odpowiedzialny za tworzenie (i niszczenie) róŜnego rodzaju technologii WWW. Jason ukończył z najwyŜszym wyróŜnieniem kierunek nauki komputerowe w Willamette University (Salem, Oregon) w 1995. Rozpoczął programowanie w Javie w lecie 1995, a z serwletami i innymi technologiami programowania po stronie serwera jest związany od grudnia 1996. JeŜeli jakimś cudem nie pracuje, przypuszczalnie moŜna go znaleźć na górskiej wędrówce. William „Will” Crawford związał się z tworzeniem stron WWW w 1995. Pracował przy programie informatycznym szpitala Children's Hospital w Bostonie, gdzie pomagał przy tworzeniu pierwszego elektronicznego systemu zapisów medycznych opartego na sieci WWW i był związany z jednymi z pierwszych korporacyjnych zastosowań języka Java. Był konsultantem projektów sieci Intranet w między innymi Children's Hospital w Massachusetts, General Hospital w Brigham, Women's Hospital, Boston Anesthesia Education Foundation i Harvard Medical Center. Will obecnie przewodzi zespołowi projektanckiemu w firmie Invantage, Inc. w Cambridge, Massachusetts, która tworzy oparte na Javie narzędzia intranetowe dla przemysłu farmaceutycznego. W wolnym czasie jest zapalonym amatorem fotografii, pisarzem i studentem ekonomii na Yale University.
Kolofon Wygląd naszych ksiąŜek jest wynikiem komentarzy czytelników, naszych własnych eksperymentów oraz komentarzy od dystrybutorów. WyróŜniające się okładki dopełniają nasze wyróŜniające się podejście do tematów technicznych, tchnące osobowość i Ŝycie w potencjalnie suche tematy. Obrazek na okładce ksiąŜki „Java Servlet — programowanie. Wydanie drugie.” przedstawia miedziany imbryk. Collen Gorman była redaktorem produkcji, a Norma Emory edytorem kopii dla „Java Servlet — programowanie. Wydanie drugie.” Catherine Moris i Leanne Soylemez były odpowiedzialne za kontrolę jakości. Firma Frameworks Consulting dostarczyła obsługi produkcji. Ellen Troutman-Zaig napisała indeks.
Hanna Dyer zaprojektowała okładkę niniejszej ksiąŜki w oparciu o projekt serii autorstwa Ediego Freedmana. Obrazek został sfotografowany przez Kevina Thomasa i dostosowany przy pomocy Adobe Photoshop przez Michaela Snowa. Emma Colby utworzyła pozostałą część okładki w programie QuarkXPress 4.1 przy pomocy czcionki Bodoni Black firmy URW Software i Bodoni Bold Italic firmy Bitstream. David Futato zaprojektował wnętrze ksiąŜki w oparciu o projekt serii autorstwa Nancy Priest. Judy Hoer dokonała konwersji plików Microsoft Word na FrameMaker 5.5.6, przy pomocy narzędzi utworzonych przez Mike'a Sierra. Czcionka nagłówków to Bodoni BT, czcionka tekstu to New Baskerville, a czcionka kodu to Constant Willison. Rysunki pojawiające się w ksiąŜce zostały utworzone przez Roberta Romano przy pomocy Macromedia FreeHand 8 i Adobe Photoshop 5.
Wstęp Od czasu, kiedy napisane zostało pierwsze wydanie niniejszej ksiąŜki, serwlety i platforma Javy działająca po stronie serwera zyskała popularność, której nie moŜna było spodziewać się w najśmielszych marzeniach. Postępuje przyłączanie tych mechanizmów do istniejących. Producenci serwerów WWW oferują obecnie obsługę serwletów jako standardową własność swojego oprogramowania. W specyfikacji Java 2, Enterprise Edition (J2EE) serwlety istnieją jako podstawowy składnik, a niemoŜliwym jest obecnie znalezienie producenta serwerów aplikacji, którego produkt nie zawierałby skalowalnej implementacji serwletów. Jest to jednak więcej niŜ zjawisko napędzane przez producentów. Serwlety stały się podstawą dla JavaServer Pages (JSP) i innych szkieletów tworzenia stron WWW, a technologia serwletów obsługuje aktualnie tak często odwiedzane witryny, jak ESPN.com i AltaVista.com. W związku z tym nie jest zaskakującym fakt, Ŝe krajobraz serwletów wygląda nieco inaczej niŜ w czasach pierwszego wydania. Interfejs serwletów (Servlet API) został poddany dwóm przeglądom, a trzeci jest w trakcie przygotowań. Znajome z początków istnienia serwletów firmy Live Software i New Atlanta, które niegdyś zarabiały sprzedając mechanizmy serwletów (nazywane teraz kontenerami serwletów) Jrun i ServletExec, zostały zauwaŜone i wykupione przez większe firmy zorientowane na WWW, odpowiednio przez Allaire i Unify. Oferują one teraz wiele własności wykraczających poza podstawową obsługę serwletów w celu odróŜnienia się od innych. Co dziwne, oficjalne pakiety javax.servlet i javax.servlet.http były pierwszymi klasami Javy, które zostały oficjalnie rozprowadzone jako Open Source. Zostały one przeniesione do projektu Apache Software Foundation (ASF), i moŜna je aktualnie odnaleźć pod adresem http://jakarta.apache.org. Pakiety te dalej zgodne są ze specyfikacją Servlet API, jednak poprawa błędów i uaktualnianie specyfikacji znajduje się teraz w rękach w zaufanych programistów Open Source — włączając autora, który miał niedawno okazję poprawienia obsługi warunkowego Ŝądania GET w HttpServlet. Dodatkowo, serwer, który jest traktowany jako wzorcowa implementacja Servlet API, został równieŜ przeniesiony do ASF i udostępniony jako Open Source pod nazwą Apache Tomcat. Od tego czasu Tomcat stał się jednym z najpopularniejszych kontenerów serwletów. Większa ilość informacji na ten temat dostępna jest pod adresem http://opensource.org. Świat serwletów zmienił się, a niniejsza ksiąŜka zawiera uaktualnione informacje. Całą wiedzę potrzebną do programowania serwletów Javy, od początku do końca. Pierwsze pięć rozdziałów opisuje podstawy — czym są serwlety, jakie działania wykonują oraz w jaki sposób pracują. Następne 15 rozdziałów zawiera informacje zaawansowane — opisuje działania podejmowane najczęściej przy pomocy serwletów oraz najpopularniejsze narzędzia do tego słuŜące. MoŜna tam znaleźć wiele przykładów, kilka wskazówek i ostrzeŜeń, a nawet opisy kilku prawdziwych błędów, które umknęły uwagi korektorów technicznych.
Servlet API 2.2 Niniejsze wydanie ksiąŜki opisuje wersję 2.2 Servlet API, która osiągnęła stan „wersji publicznej” w sierpniu 1999, a stan „wersji ostatecznej” w grudniu 1999. Wydanie pierwsze opisywało wersje 2.0. Zmiany pomiędzy wersjami 2.0 i 2.2 są znaczne: •
Zostały wprowadzone zasady definiujące dystrybucje serwletów pomiędzy kilkoma serwerami wspierającymi.
•
Serwlety korzystają aktualnie z dołączanych aplikacji WWW, które mogą być konfigurowane i wdraŜane w sposób niezaleŜny od serwera.
•
Znacznie poprawione zostało bezpieczeństwo serwletów.
•
Serwlety mogą teraz przekazywać obsługę Ŝądań innym składnikom serwera.
•
Serwlety mogą teraz dzielić się informacjami przy pomocy ich ServletContext
•
Istnieje sposób przystosowania serwletów do obsługi dostępu rozproszonego.
•
Serwlety posiadają teraz ściślejszą kontrolę nad zarządzaniem sesją.
•
Dodane zostało buforowanie odpowiedzi.
•
Rozszerzona została kontrola nad nagłówkami HTTP.
•
Aktualnie moŜe być zastosowana bardziej zaawansowana obsługa błędów.
•
API został „wyczyszczony” w celu nadania większej spójności i przewidywalności nazwom metod.
•
Servlet API jest teraz zdefiniowany poprzez formalny dokument specyfikacji, a przyszłe uaktualnienia API są zarządzane przez formalny proces Java Specification Request (JSR).
•
Serwlety są teraz zintegrowane z podstawową specyfikacją platformy Java 2, Enterpise Edition (J2EE).
Wszystkie te zmiany, oraz wiele innych drobnych usprawnień, są w pełni opisane w niniejszym nowym wydaniu. Drugie wydanie zawiera równieŜ obszerny opis najciekawszego obszaru programowania serwletów — technik tworzenia prawdziwych dynamicznych witryn opartych na serwletach. W niniejszym wydaniu znajdują się samouczki pięciu najpopularniejszych technologii tworzenia zawartości opartej na serwletach, naleŜących do Open Source: •
JavaServer Pages (JSP), standard firmy Sun, tworzony i udostępniany w połączeniu z serwletami
•
Tea, technologia utworzona przez Walt Disney Internet Group (dawniej GO.com), zastosowany w wielu bardzo często odwiedzanych stronach, takich jak ESPN.com, NFL.com, Disney.com, DisneyLand.com, GO.com i Movies.com
•
WebMacro, utworzony przez Semiotek i wykorzystywany przez wyszukiwarkę AltaVista
•
XMLC, utworzony przez Lutris Technologies w celu udostępnienia mocy technologii XML sieci WWW, wykorzystywany przez innowacyjne witryny takie jak customatix.com
•
Element Construcion Set (ECS), utworzony przez Apache w celu obsługi najbardziej wymagających potrzeb programistycznych
Niniejsze drugie wydanie opisuje równieŜ WAP, Wireless Application Protocol (Protokół Aplikacji Bezprzewodowych) oraz wyjaśnia, jak tworzyć oparte na serwletach aplikacje WWW dla urządzeń bezprzewodowych.
Servlet API 2.3 W czasie pisania niniejszej ksiąŜki, Servlet API 2.3 jest w trakcie tworzenia. Jednak nie został on jeszcze ukończony. W związku z tym tekst niniejszego wydania zawiera w róŜnych miejscach krótkie uwagi na temat zmian spodziewanych w z Servlet API 2.3. Dodatkowo, ostatni rozdział ksiąŜki zawiera dokładniejszy opis próbnej specyfikacji Servlet API 2.3, udostępnionej w październiku 2000, który pozwala na zapoznanie się z najnowszymi własnościami Servlet API 2.3. NaleŜy jednak zaznaczyć, Ŝe specyfikacje te ciągle podlegają zmianom, a ostateczna wersja moŜe się nieco róŜnić od materiału tu przedstawionego.
Czytelnicy pierwszego wydania Czytelnicy ksiąŜki „Java Servlet Programming, 1st ed.” zorientują się, Ŝe niniejsza ksiąŜka została obszernie uaktualniona do Servlet API 2.2 i, gdzie to tylko moŜliwe, Servlet 2.3. KaŜdy rozdział został znacząco poprawiony w porównaniu z pierwszym wydaniem, a takŜe dodano sześć nowych rozdziałów opisujących techniki tworzenia zawartości opartej na serwletach, jak równieŜ nowy rozdział siódmy, „Serwlety korporacyjne i J2EE”, który opisuje integrację serwletów w platformie J2EE. Ze względu na znaczący wpływ modelu aplikacji WWW na wszystkie aspekty programowania serwletów, poleca się czytelnikom pierwszego wydania przeczytanie kaŜdego interesującego ich rozdziału oraz zwrócenie
uwagi na nowe mechanizmy, które pozwalają na wykonanie tradycyjnych zadań. Czytelnicy dysponujący ograniczonym czasem powinni przejrzeć listę najbardziej znaczących zmian w podrozdziale „Organizacja”.
Czytelnicy Dla kogo jest ta ksiąŜka? Dla osób zainteresowanych tworzeniem aplikacji umieszczanych w sieci WWW. Dokładniej rzecz biorąc, niniejszą ksiąŜką powinni zainteresować się: •
Programiści J2EE — serwlety są integralną częścią standardu Java 2, Enterpise Edition. Programiści tworzący aplikacje dla serwerów J2EE mogą nauczyć się jak najlepiej zintegrować serwlety z innymi podobnymi technologiami.
•
Programiści JSP — JavaServer Pages (JSP) tworzone są na podstawie serwletów. Wykorzystanie pełnej mocy JSP wymaga zrozumienia serwletów, co teŜ umoŜliwia niniejsza ksiąŜka. Zawiera ona równieŜ samouczek JSP oraz czterech podstawowych konkurencyjnych technologii.
•
Programiści apletów Javy — porozumiewanie się apletów z serwerem zawsze sprawiało problemy. Serwlety ułatwiają to zadanie poprzez dostarczenie apletom prostego w połączeniu agenta na serwerze.
•
Programiści CGI — CGI jest popularną metodą rozszerzania funkcjonalności serwera WWW. Serwlety są elegancką i wydajną alternatywą tej techniki.
•
Programiści innych technik serwerów — istnieje wiele alternatyw dla CGI, między innymi FastCGI, PHP, NSAPI, WAI, ISPAI, ASP, a teraz ASP+. KaŜda z nich posiada ograniczenia związane z przenośnością, bezpieczeństwem, wydajnością i/lub integracją z innymi źródłami danych. Serwlety przewyŜszają je w kaŜdym z tych obszarów.
Co naleŜy wiedzieć Podczas rozpoczynania pracy z niniejszą ksiąŜką, niespodzianką dla autorów okazało się, Ŝe jedną z najtrudniejszych do określenia rzeczy jest docelowy czytelnik. Czy zna on Javę? Czy ma doświadczenie w programowaniu CGI lub innych aplikacji WWW? Czy miał juŜ kontakt z serwletami? Czy zna HTTP i HTML, czy te skróty brzmią dla niego zupełnie niezrozumiale? NiezaleŜnie od przyjmowanego poziomu doświadczenia, zawsze okazywało się, Ŝe ksiąŜka będzie zbyt uproszczona dla jednych uŜytkowników, a zbyt zaawansowana dla drugich. Ostatecznie zdecydowano się na zasadę, Ŝe niniejsza ksiąŜka powinna zawierać w przewaŜającej części materiał oryginalny — moŜna pominąć obszerne opisy tematów i koncepcji dobrze opisanych w sieci lub innych ksiąŜkach. W tekście znaleźć moŜna odwołania do tych zewnętrznych źródeł informacji. Oczywiście zewnętrzne źródła informacji nie są wystarczające. Niniejsza ksiąŜka zakłada, Ŝe czytelnicy dobrze znają język Java oraz podstawowe techniki programowania obiektowego. JeŜeli nie spełnia się tych załoŜeń, polecane jest przygotowanie się poprzez przeczytanie ogólnej ksiąŜki na temat programowania w Javie, takiej jak „Learning Java” autorstwa Patricka Niemeyera i Jonathana Knudsena (O'Reilly). W ksiąŜce tej moŜna jedynie krótko zapoznać się z rozdziałami na temat apletów i programowania Swing (graficznego), a skupić się na sieci i programowaniu wielowątkowym. Aby zacząć od razu naukę serwletów i uczyć się Javy w trakcie, polecane jest przeczytanie niniejszej ksiąŜki równocześnie z „Java in a Nutshell” autorstwa Davida Flanagana (O'Reilly) lub innym podręcznikiem. Niniejsza ksiąŜka nie wymaga od czytelników doświadczenia w programowaniu WWW, HTTP i HTML. Nie zawiera jednak pełnego wprowadzenia lub wyczerpującego opisu tych technologii. Opisane zostaną podstawy potrzebne do efektywnego programowania serwletów, a szczegóły (takie jak pełna lista znaczników HTML i nagłówków HTTP 1.1) pozostawione zostaną innym źródłom.
Przykłady W niniejszej ksiąŜce znaleźć moŜna ponad 100 przykładów serwletów. Ich kod jest całkowicie zawarty wewnątrz tekstu, moŜliwe jest jednak takŜe pobranie przykładów zamiast ręcznego ich wpisywania. Kod przykładów, spakowany i gotowy do pobrania, moŜna znaleźć pod adresem
http://www.oreilly.com/catalog/jservlet2. Wiele z tych serwletów moŜna zobaczyć w działaniu pod adresem http://www.servlets.com. Wszystkie przykłady zostały przetestowane przy pomocy serwera Apache Tomcat 3.2 działającego w trybie samodzielnym, wirtualnej maszyny Javy (Java Virtual Machine — JVM) zawartej w Java Development KIT 1.1.8 i 1.2.2, zarówno pod Windows jak i Uniksem. Kilka zaawansowanych przykładów wymaga własności, których nie obsługuje Tomcat w trybie samodzielnym. W tym przypadku przykłady były testowane na róŜnych innych serwerach, jak opisano w tekście. Serwer Apache Tomcat jest oficjalną wzorcową implementacją Servlet API, i jest dostępny w licencji Open Source pod adresem http://jakarta.apache.org. Niniejsza ksiąŜka zawiera równieŜ zbiór klas narzędziowych — wykorzystywane są one przez serwlety przykładowe, mogą się takŜe okazać przydatne przy tworzenie własnych. Klasy te zawarte są w pakiecie com.oreilly.servlet. Między innymi są to klasy pomagające serwletom w analizie parametrów, obsłudze wysyłania plików, generowaniu wieloczęściowych odpowiedzi (przepychanie serwera), negocjacji ustawień lokalnych i internacjonalizacji, zwracaniu plików, zarządzaniu połączeniami i pracy jako serwer RMI. Pakiet te zawiera równieŜ klasę wspomagającą komunikację apletów z serwletami. Od czasu pierwszego wydania dodane zostały nowe klasy pomagające serwletom w wysyłaniu wiadomości poczty elektronicznej, przechowywaniu odpowiedzi w pamięci podręcznej oraz automatycznym wykrywaniu obsługi Servlet API. Kod źródłowy większości pakietu com.oreilly.servlet zawarty jest w tekście, a pełna, aktualna wersja jest dostępna w formie elektronicznej (razem z dokumentacją javadoc) pod adresem http://www.servlets.com.1
Organizacja Niniejsza ksiąŜka składa się z 20 rozdziałów i 6 dodatków, są one następujące:
1
•
Rozdział 1, „Wprowadzenie”. Wyjaśnia rolę i zalety serwletów Javy w tworzeniu aplikacji WWW. W drugim wydaniu dodane zostały dodatkowe informacje na temat serwerów.
•
Rozdział 2, „Podstawy serwletów HTTP”. Zawiera krótkie wprowadzenie do HTTP i funkcji, jakie mogą pełnić serwlety HTTP. Przedstawia tworzenie prostej strony i wprowadza pojęcie dołączanej aplikacji WWW. Drugie wydanie opisuje aplikacje WWW i ich deskryptory oparte na XML.
•
Rozdział 3, „Cykl Ŝycia serwletów”. Wyjaśnia szczegółowe informacje na temat sposobu i czasu ładowania serwletów, sposobu i czasu ich wykonywania, zarządzania wątkami oraz obsługi kwestii synchronizacji w systemie wielowątkowym. Opisane są równieŜ stany trwałe. Drugie wydanie zawiera nowe zasady kontekstowego przeładowywania i rejestracji serwletów, nowy podrozdział na temat pamięci podręcznej po stronie serwera oraz uwagę na temat super.init(config).
•
Rozdział 4, „Pobieranie informacji”. Wprowadza najpopularniejsze metody wykorzystywane przez serwlety w celu pobrania informacji — na temat klienta, serwera, Ŝądań klienta oraz samego siebie. Przedstawia równieŜ działanie ogólnej klasy słuŜącej do wysyłania plików. Drugie wydanie opisuje ustawianie informacji w deskryptorze, pobieranie nazwy serwletu, dostęp do katalogów tymczasowych, obsługę kontekstowych parametrów początkowych, określanie wersji Servlet API, przypisywanie odwzorowania serwletów oraz dostęp do zasobów abstrakcyjnych. Przestawia równieŜ poprawiony, bardziej elastyczny składnik słuŜący do wysyłania plików.
•
Rozdział 5, „Wysyłanie informacji HTML”. Opisuje sposoby tworzenia kodu HTML przez serwlet, zwracania błędów, buforowania odpowiedzi, przekierowywania Ŝądań, zapisywania danych w dzienniku zdarzeń serwera oraz wysyłania dostosowanych nagłówków HTML. Drugie wydanie zawiera nowy opis buforowania odpowiedzi, bardzo przydatny przykład przekierowywania oraz nowe podrozdziały na temat konfiguracji stron zawierających błędy i obsługi błędów.
Niniejsza ksiąŜka nie zawiera CD-ROM-u. Dołączenie CD-ROM-u podnosi koszty produkcji a w związku z tym cenę ksiąŜki. ZałoŜono, Ŝe kaŜdy Czytelnik posiada dostęp do Internetu, a w związku z tym moŜe oszczędzić pewną ilość pieniędzy poprzez pobranie kodu przykładów przez sieć WWW. Nie uwaŜa się równieŜ za sensowne dołączanie wersji próbnych róŜnych serwerów WWW i aplikacji. ZwaŜywszy na nieustanny szybki postęp na rynku serwletów, dołączone serwery stałyby się przestarzałe jeszcze przed wydrukowaniem ksiąŜki. Te same wersje próbne dostępne są w sieci i poleca się pobranie ich własnoręcznie. Proszę pamiętać, Ŝe jeŜeli zamierza się czytać niniejszą ksiąŜkę offline, polecane jest pobranie kodu przykładów i serwera WWW Apache Tomcata, kiesy tylko będzie to moŜliwe. Łącza do pobrań umieszczone są pod adresem http://www.servlets.com.
•
Rozdział 6, „Wysyłanie zawartości multimedialnej”. Opisuje róŜne interesujące dane, które moŜe zwracać serwlet — zawartość WAP/WML dla urządzeń bezprzewodowych, dynamicznie tworzone obrazki, zawartość skompresowana oraz odpowiedzi wieloczęściowe. W drugim wydaniu dodano opis WAP/WML, listy plików powitalnych, dyskusję na temat PNG, usprawnioną pamięć podręczną rysunków po stronie serwera oraz więcej szczegółów na temat tworzenia zawartości skompresowanej.
•
Rozdział 7, „Śledzenie sesji”. Opisuje sposoby tworzenia śledzenia stanu w bezstanowym protokole HTTP. Pierwsza część rozdziału opisuje tradycyjne techniki śledzenia sesji stosowane przez programistów CGI. Druga część opisuje sposoby zastosowania wbudowanej w Servlet API obsługi śledzenia sesji. Drugie wydanie zawiera zasady tworzenia sesji aplikacji WWW, materiał na temat nowych nazw metod sesji, dyskusję na temat zarządzania przekraczaniem czasu oraz śledzenie sesji oparte na apletach.
•
Rozdział 8, „Bezpieczeństwo”. Wyjaśnia kwestie bezpieczeństwa związane z programowanie rozproszonym. Opisuje sposoby korzystania ze standardowych funkcji serwletów związanych z zarządzaniem kontami uŜytkowników oraz sposoby tworzenia bardziej zaawansowanego systemu przy pomocy dodatkowego uwierzytelniania i autoryzacji. Wyjaśni równieŜ rolę serwletów w bezpiecznej komunikacji SSL. W drugim wydaniu całkowicie przeredagowany.
•
Rozdział 9, „Łączność z bazami danych”. Opisuje sposoby wykorzystania serwletów w wysokowydajnej łączności z bazami danych WWW. Zawiera samouczek JDBC. Drugie wydanie zawiera przykłady konfiguracji połączeń z plikami właściwości, nowy przykład księgi gości oraz nowy podrozdział opisujący JDBC 2.0.
•
Rozdział 10, „Komunikacja aplet-serwlet”. Opisuje sposoby wykorzystania serwletów przez aplet, który musi porozumieć się z serwerem. Uaktualniony w drugim wydaniu.
•
Rozdział 11, „Współpraca serwletów”. Opisuje powody komunikacji serwletów i sposoby ich współpracy przez dzielenie się informacjami lub wywoływanie sienie nawzajem. W drugim wydaniu całkowicie przeredagowany.
•
Rozdział 12, „Serwlety korporacyjne i J2EE”. Opisuje zaawansowane własności serwletów wykorzystywane w witrynach korporacyjnych — dystrybucję ładunku i integrację składników J2EE. Nowość w drugim wydaniu.
•
Rozdział 13, „Internacjonalizacja”. Opisuje sposoby, dzięki którym serwlet moŜe odczytywać i tworzyć zawartość w róŜnych językach. Drugie wydanie opisuje zastosowanie javadoc w zarządzaniu kodowaniem i sposoby wykorzystywania nowych metod API w zarządzaniu wersjami lokalnymi.
•
Rozdział 14, „Szkielet Tea”. Przedstawia szkielet Tea, elegancki, ale zarazem potęŜny mechanizm szablonów. Nowość w drugim wydaniu.
•
Rozdział 15, „WebMacro”. Opisuje szkielet WebMacro, podobny do Tea lecz z kilkoma innymi decyzjami projektanckimi. Nowość w drugim wydaniu.
•
Rozdział 16, „Element Construction Set”. Zawiera krótki opis ECS, obiektowego podejścia do tworzenia strony. Nowość w drugim wydaniu.
•
Rozdział 17, „XMLC”. Przegląd XMLC, podejścia do tworzenia strony opartego na XML. Nowość w drugim wydaniu.
•
Rozdział 18, „JavaServer Pages”. Wyjaśnia JSP, standardową technologię firmy Sun, w której strony WWW są automatycznie wkompilowane w serwer. Nowość w drugim wydaniu.
•
Rozdział 19, „Informacje dodatkowe”. Przedstawia dodatkowe przykłady serwletów i podpowiedzi, które nie zmieściły się w Ŝadnym z poprzednich rozdziałów. Drugie wydanie zawiera analizator parametrów zlokalizowanych, nową klasę poczty elektronicznej oraz uaktualniony podrozdział na temat wyraŜeń regularnych, nowy podrozdział na temat dodatkowych narzędzi oraz dodatkowe podpowiedzi na temat wydajności.
•
Rozdział 20, „Zmiany w Servlet API 2.3”. Opisuje zmiany w nadchodzącej wersji 2.3 Servlet API, który ma zostać udostępniony w połowie 2001. Nowość w drugim wydaniu.
•
Dodatek A, „Krótki opis Servlet API”. Zawiera pełny opis klas, metod i zmiennych w pakiecie javax.servlet. W drugim wydaniu uaktualniony do Servlet API 2.2
•
Dodatek B, „Krótki opis HTTP Servlet API”. Zawiera pełny opis klas, metod i zmiennych w pakiecie javax.servlet.http. W drugim wydaniu uaktualniony do Servlet API 2.2
•
Dodatek C, „Krótki opis deskryptorów DTD”. Przedstawia opis deskryptora Document Type Definition (Definicja Typu Dokumentu) web.xml. Nowość w drugim wydaniu.
•
Dodatek D, „Kody stanu HTTP”. Lista kodów stanu określonych przez HTTP, a takŜe stałe mnemoniczne wykorzystywane przez serwlety.
•
Dodatek E, „Encje znakowe”. Lista encji znakowych zdefiniowanych w HTML, a takŜe równowaŜne do nich wartości kodów ucieczkowych Uniksa.
•
Dodatek F, „Kodowania”. Lista sugerowanych kodowań wykorzystywanych przez serwlety w celu tworzenia zawartości w róŜnych językach.
Proszę czuć się swobodnie i czytać rozdziały w niniejszej ksiąŜce w dowolnej kolejności. Czytanie prosto od początku do końca zapewnia uniknięcie wszelkich niespodzianek, jako Ŝe starano się unikać odwołań do dalszych części ksiąŜki. Przeskakiwanie jest jednak moŜliwe, zwłaszcza po rozdziale 5 — pozostała część rozdziałów została zaprojektowana w celu oddzielonego istnienia. Jedna ostatnia sugestia — proszę przeczytać podrozdział „Usuwanie błędów” w rozdziale 19, jeŜeli kiedykolwiek napotka się fragment kodu pracujący nieprawidłowo.
Konwencje wykorzystywane w tej ksiąŜce Kursywa wykorzystywana jest do: •
ŚcieŜek, nazw plików i programów
•
Nowych terminów podczas ich definiowania
•
Adresów internetowych, takich jak nazwy domen i URL-e
Czcionka pogrubiona wykorzystywana jest do: •
Konkretnych klawiszy na klawiaturze
•
Nazw przycisków interfejsu uŜytkownika i menu
Czcionka o stałej szerokości wykorzystywana jest do: •
Wszystkich danych pojawiających się dokładanie w programie Javy, takich jak słowa kluczowe, typy danych, stałe, nazwy metod, zmienne, nazwy klas oraz nazwy interfejsów
•
Wszystkich wydruków kodu Javy
•
Dokumentów HTML, znaczników i atrybutów
Czcionka o stałej szerokości z kursywą wykorzystywana jest do: •
Ogólnych obszarów zablokowanych wskazujących, Ŝe dany element jest zastępowany w programie przez konkretną wartość.
Pogrubiona czcionka o stałej szerokości wykorzystywana jest do: •
Wpisów w wierszu poleceń
Prośba o komentarze Prosimy o pomoc w poprawieniu następnych wydań poprzez zgłaszanie wszystkich błędów, nieścisłości, niejasnych lub niewłaściwych wyraŜeń oraz zwykłych literówek, które moŜna odnaleźć w dowolnym miejscu niniejszej ksiąŜki. Proszę wysyłać komunikaty o błędach i komentarze pod adres [email protected]. (Przed wysłaniem komunikatu o błędzie prosimy sprawdzić erratę na stronie http://www.oreilly.com/catalog/jservlet2 w celu sprawdzenia, czy dany błąd nie został juŜ opisany.)
Prosimy równieŜ o opinie, co powinno znaleźć się w tej ksiąŜce, aby stała się ona bardziej przydatna. Wydawnictwo traktuje takie komentarze bardzo powaŜnie i próbuje dołączyć rozsądne sugestie do przyszłych wydań ksiąŜki.
Podziękowania Kiedy pracowałem nad niniejszą ksiąŜką, przyjaciel powiedział mi „Łatwiej musi być pisać drugie wydanie; napisałeś juŜ raz tę ksiąŜkę”. Pomyślałem nad tym przez chwilę, roześmiałem się i odpowiedziałem, „To jest łatwiejsze, ale ani trochę nie aŜ tak łatwe, jak się spodziewałem!”. Patrząc wstecz, myślę Ŝe powód tego ma niewiele wspólnego z ksiąŜkami, a bardziej z technologią. Pierwsze wydanie opisywało Servlet API 2.0, specyfikację tworzoną przez około dwa lata. Niniejsze drugie wydanie przedstawia Servlet API 2.2 i 2.3, co daje mniej więcej dwa dodatkowe lata pracy projektantów. Tak więc jedynie z tej perspektywy moŜna dostrzec, Ŝe jeŜeli pierwsze wydanie zabrało mniej więcej rok aktywnego pisania, to drugie powinno zabrać mniej więcej tyle samo czasu. I rzeczywiście tak było — około 9 miesięcy. Wiele osób pomogło mi w tworzeniu tej ksiąŜki. Jestem im głęboko wdzięczny. Po pierwsze są to redaktorzy techniczni ksiąŜki — James Duncan Davidson, przewodniczący specyfikacji Servlet API 2.1 i 2.2, oraz Danny Coward, przewodniczący nadchodzącej wersji 2.3. Wszystko, co moŜna o nich powiedzieć dobrego, to za mało. Nie tylko dostarczyli mi nieocenionej pomocy i rad w trakcie pisania ksiąŜki, lecz stworzyli wszystkim doskonałą platformę do programowania dla WWW. Dziękuję równieŜ wielu programistom, którzy swoim doświadczeniem wspomogli tworzenie rozdziałów na temat tworzenia zawartości (i w wielu przypadkach tworzyli opisywaną technologię) — Reece Wilton i Brian O'Neill dla Tea, Justin Wells dla WebMacro, Jon Stevens dla ECS, Mark Diekhnas i Christian Cryder dla XMLC oraz Hans Bergsten i Craig McClanahan dla JSP. Chciałbym równieŜ podziękować Bobowi Ecksteinowi, redaktorowi ksiąŜki, którego ręczne notatki były zawsze celne, choć czasami niemoŜliwe do odcyfrowania. Bob przejął obowiązki redaktorskie od Pauli Ferguson, po tym, jak zajęła się ona zarządzaniem ksiąŜkami O'Reilly na temat WWW i skryptów. Dziękuję równieŜ Jimowi Grishamowi, który pomógł zlokalizować wszystkie rodzaje komputerów i przeglądarek wykorzystywane przy testowaniu przykładów; Magnusowi Stenmanowi z firmy Orion, który wyjaśnił mi implementację J2EE w serwerze Orion; Justynie Horwat, zwanej przez niektórych Boginią Biblioteki Znaczników, za odpowiedzi na pytania dotyczący biblioteki znaczników JSP oraz Ethanowi Henry, który pomógł sugestiami na temat poprawiania wydajności serwletów. Nie mogę zapomnieć o Brett'cie McLaughlinie, autorze ksiąŜki „Java and XML” (O'Reilly) i współtwórcy JDOM. Jego współpraca ze mną na temat JDOM właściwie spowolniła pisanie tej ksiąŜki, lecz prędkość, z jaką on pisze inspiruje mnie, a poniewaŜ wspomniał mnie on w swojej ksiąŜce, muszę napisać coś tutaj. I ostatecznie dziękuję mojej dziewczynie, Kathlyn Bautista, która nie narzekała, kiedy pracowałem w niedziele, lecz sprawiała, Ŝe wcale pracować nie chciałem. Jason Hunter Listopad 2000
Podziękowania z wydania pierwszego Historia tej ksiąŜki rozpoczęła się właściwie 20 marca 1997, w księgarni „Computer Literacy” w San Jose w Kalifornii. Tam — po ciekawej rozmowie z Larrym Wallem i Randallem Schwartzem, w której Larry wyjaśniał, jak automatyzuje swój dom przy pomocy Perla — spotkałem po raz pierwszy szacownego Tima O'Reilly. Przedstawiłem się i bezczelnie powiedziałem, Ŝe pewnego dnia (w dalekiej przyszłości, myślałem), planuję napisać ksiąŜkę dla O'Reilly. Czułem się jakbym mówił Stevenowi Spielbergowi, Ŝe chcę zagrać główną rolę w jego filmie. Ku mojemu kompletnemu zaskoczeniu, Tim odpowiedział, „Na jaki temat?”. Tak rozpoczęła się szaleńcza jazda prowadząca do powstania tej ksiąŜki. Wystąpiło w tym czasie kilka jasnych punktów, które z dumą pamiętam — poznanie mojej redaktorki (świetnie, teŜ jest młoda!), podpisania oficjalnego kontraktu (czy wiecie, Ŝe cały papier firmowy O'Reilly jest ozdobiony zwierzętami?), napisanie pierwszego zdania (znowu i znowu), drukowanie pierwszego rozdziału (i sprawienie,
Ŝeby wyglądał on jak ksiąŜka O'Reilly), po czym oglądanie rosnącej sterty wydruków, do momentu, kiedy nie zostało juŜ nic do napisania (oprócz podziękowań). Było równieŜ kilka trudnych chwil. W pewnym momencie, kiedy ksiąŜka była ukończona w połowie, uświadomiłem sobie, Ŝe Servlet API zmieniał się szybciej, niŜ mogłem nadąŜyć. Wierzę w powiedzenie „JeŜeli coś się nie udaje, poproś o pomoc”, tak więc po krótkich poszukiwaniach poprosiłem Williama Crawforda, który pracował w tym czasie nad ksiąŜką „Java Enterprise in a Nutshell”, czy pomógłby mi w przyśpieszeniu pracy nad ksiąŜką. Wspaniałomyślnie zgodził się on i pomógł w napisaniu dwóch rozdziałów, a takŜe części dodatków. Wielu innych ludzi pomogło mi w napisaniu niniejszej ksiąŜki, zarówno bezpośrednio jak i pośrednio. Chciałbym podziękować Pauli Ferguson, redaktorowi ksiąŜki oraz Mike'owi Loukidesowi, redaktorowi serii Java, za ich starania o zapewnienie (i poprawę) jakości tej ksiąŜki. Oraz Timowi O'Reilly za danie mi szansy spełnienia marzeń. Dziękuję równieŜ moim menedŜerom w firmie Silicon Graphics, Kathy Tansill i Waltowi Johnsonowi, za dostarczenie większej pomocy i elastyczności niŜ miałem prawo się spodziewać. KaŜde podziękowania są niewystarczające dla inŜynierów firmy Sun, którzy odpowiadali na niezliczone pytania, informowali mnie o zmianach w Servlet API i naprawiali niemal kaŜdy błąd, jaki zgłosiłem — są to James Duncan Davidson (Wyglądający niemal jak James Gosling), Jim Driscoll, Rob Clark i Dane Brownell. Dziękuję równieŜ członkom listy dystrybucyjnej jserv-interest, których pytania i odpowiedzi ukształtowały zawartość tej ksiąŜki; Willowi Rameyowi, staremu przyjacielowi, który nie pozwolił, aby przyjaźń przesłoniła jego krytyczne oko; Mike'owi Engberowi, człowiekowi, do którego zwróciłem się po ucieczce z eleganckich miejsc pracy i byłem gotowy na zaakceptowanie jego szalonych pomysłów; Dave'owi Vandergriftowi, pierwszej osobie, która przeczytała wiele rozdziałów; Billowi Dayowi, autorowi „Java Media Players”, który pomagał poprzez przechodzenie przez proces tworzenia ksiąŜki równolegle ze mną; Michaelowi O'Connellowi i Jill Steinberg, redaktorom „JavaWorld”, dzięki którym napisałem mój pierwszy profesjonalny tekst; Dougowi Youngowi, który dzielił się za mną technicznymi sztuczkami poznanymi przy pisaniu siedmiu własnych ksiąŜek technicznych oraz Shoji Kuwabara'rze, Mieko Aono, Song'owi Yung'owi, Matthew Kim'owi oraz Alexandrowi Pashintsev'owi za ich pomoc w przetłumaczeniu skryptu „Witaj Świecie” w rozdziale 13. Chciałbym gorąco podziękować recenzentom technicznym ksiąŜki, których konstruktywny krytycyzm pomógł znacznie w usprawnieniu pracy — są to Mike Slinn, Mike Hogarth, James Duncan Davison, Dan Protchett, Dave McMurdie i Rob Clark. Ciągle jestem w szoku, po tym jak dowiedziałem się, Ŝe jednemu recenzentowi zabrało trzy dni, aby przeczytać to, nad czego stworzeniem pracowaliśmy rok! Ostatecznie, dziękuję Mamie i Tacie, za ich miłość i wsparcie i za czas, który poświęciliście dawno temu dna nauczenie mnie podstaw pisania. Dziękuję teŜ Kristi Taylor, która sprawiła, Ŝe ta niewielka część czasu, która nie była wypełniona pracą, stała się przyjemnością. Oraz Dziadkowi, chciałbym, Ŝebyś mógł to zobaczyć. Jason Hunter Czerwiec 1998 Po pierwsze dziękuję Shelley Norton, dr Isaacowi Kohane, dr Jamesowi Facklerowi i dr Richardowi Kitzowi (a takŜe pozostałej części zespołu, której wkład pozostaje nieoceniony), których pomoc i wsparcie sprawiła, Ŝe wszystko to stało się moŜliwe. A takŜe Martinowi Streeterowi z firmy Invantage, Inc., za jego wsparcie w trakcie trwania tego projektu. Bez Roba Leitha, Rogera Stacey i Freda Sterbeigha, przypuszczalnie ciągle trwałbym w stronie biernej. Dale Dogherty zaoferował mi pieniądze w zamian za słowa, wydarzenie, którego ciągle nie potrafię pojąć. Andy Kwak, Joel Pomerantz i Matthew Proto, wspaniali ludzie, zechcieli przeczytać próbne wydruki i słuchać skarg o godzinie pierwszej w nocy. I, oczywiście Mamie i Tacie za ich lata wsparcia, oraz mojej siostrze Faith za (zazwyczaj) wybaczanie mi bycia durniem. William Crawford Lipiec 1998
W niniejszym rozdziale: •
Historia aplikacji WWW
•
Obsługa serwletów
•
Moc serwletów
Rozdział 1.
Wprowadzenie Rozwój aplikacji Javy działających po stronie serwera — wszystko od działających samodzielnie serwletów do pełnej platformy Java 2, Enterprise Edition (J2EE) — był jednym z najbardziej ekscytujących trendów w programowaniu Javy. Język Java został utworzony pierwotnie w celu zastosowania w małych, osadzonych urządzeniach. Był on opisywany jako język do tworzenia zawartości WWW po stronie klienta w formie apletów. Jednak aŜ do kilku ostatnich lat potencjał Javy jako platformy do programowania po stronie serwera był niestety pominięty. Aktualnie Java jest uwaŜana za język idealnie nadający się do programowania po stronie serwera. Szczególnie szybko rozpoznały potencjał Javy w serwerach firmy biznesowe — Java idealnie pasuje do duŜych aplikacji typu klient-serwer. NiezaleŜna od platformy natura Javy jest niezwykle uŜyteczna dla organizacji posiadających heterogeniczny zbiór serwerów pracujących pod róŜnymi odmianami systemów operacyjnych UNIX i Windows (oraz coraz bardziej Mac OS X). Nowoczesny, obiektowy i chroniący pamięć projekt Javy pozwala programistom na skrócenie cyklów programistycznych i zwiększenie niezawodności. Dodatkowo, wbudowana w Javę obsługa sieci i interfejsów korporacyjnych dostarcza moŜliwości dostępu do starych danych, ułatwiając przejście ze starszych systemów klient-serwer. Serwlety Javy są kluczowym składnikiem programowania Javy po stronie serwera. Serwlet to małe, dołączane rozszerzenie serwera, które rozszerza jego funkcjonalność. Serwlety pozwalają programistom na rozszerzanie i dostosowywanie kaŜdego serwera WWW lub aplikacji z obsługą Javy do wcześniej nieznanego poziomu przenośności, elastyczności i łatwości. Jednak przed przejściem do szczegółów, naleŜy spojrzeć na sprawę z pewnej perspektywy.
Historia aplikacji WWW ChociaŜ serwlety mogą być wykorzystywane do rozszerzenia funkcjonalności kaŜdego serwera z obsługą Javy, najczęściej uŜywane są do rozszerzania serwerów WWW, stanowiąc potęŜny i wydajny zamiennik dla skryptów CGI. Kiedy wykorzystuje się serwlet do utworzenia dynamicznej zawartości strony WWW lub podniesienia w inny sposób funkcjonalności serwera WWW, w efekcie tworzy się aplikację WWW. Podczas, gdy strona WWW wyświetla jedynie zawartość statyczną i pozwala uŜytkownikowi na nawigację poprzez tę zawartość, aplikacja WWW dostarcza doświadczenia bardziej interaktywnego. Aplikacja WWW moŜe być tak prosta jak
wyszukiwanie słowa kluczowego w archiwum dokumentów lub tak złoŜona, jak sklep elektroniczny. Aplikacje WWW są umieszczane w Internecie oraz korporacyjnych sieciach intranet i extranet, w których posiadają one potencjał do zwiększania produktywności i zmiany sposobu prowadzenia biznesu przez małe i duŜe firmy. Aby zrozumieć potęgę serwletów, naleŜy cofnąć się i spojrzeć na pewne inne podejścia do tworzenia aplikacji WWW.
Common Gateway Interface Common Gateway Interface (Wspólny Interfejs Bramek), w skrócie CGI, był jednym z pierwszych praktycznych technik tworzenia zawartości dynamicznej. Przy pomocy CGI serwer WWW przekazuje konkretne Ŝądania do programu zewnętrznego. Wynik tego programu jest później przesyłany do klienta w miejscu statycznego pliku. Powstanie CGI pozwoliło na implementację wielu nowych rodzajów funkcjonalności na stronach WWW, a CGI szybko stał się de facto standardem, zaimplementowanym w ogromnej ilości serwerów WWW. Interesujący jest fakt, Ŝe moŜliwość tworzenia przez programy CGI dynamicznych stron WWW jest ubocznym efektem ich początkowego przeznaczenia — zdefiniowania standardowej metody porozumiewania się serwera informacji z aplikacjami zewnętrznymi. To źródło wyjaśnia, dlaczego CGI posiada przypuszczalnie najgorszy do wyobraŜenia okres trwałości. Kiedy serwer otrzymuje Ŝądanie, które uzyskuje dostęp do programu CGI, musi on utworzyć nowy proces w celu uruchomienia programu CGI i potem przekazania mu, poprzez zmienne środowiskowe i standardowe wpisy, kaŜdego bitu informacji, który moŜe być potrzebny do wygenerowania odpowiedzi. Tworzenie procesu dla kaŜdego takiego Ŝądania wymaga czasu i znaczących zasobów serwera, co ogranicza liczbę Ŝądań, które serwer moŜe obsługiwać równocześnie. Rysunek 1.1 przedstawia okres trwałości CGI.
Rysunek 1.1. Okres trwałości CGI ChociaŜ program CGI moŜe być utworzony w prawie kaŜdym języku, język programowania Perl stał się podstawową opcją. Zaawansowane moŜliwości formatowania tekstu Perla stanowią ogromną pomoc w zarządzaniu szczegółami interfejsu CGI. Tworzenie skryptu CGI w Perlu pozwala na uniezaleŜnienie o platformy, ale wymaga równieŜ uruchomienia osobnego interpretatora Perla dla kaŜdego Ŝądania, co zabiera jeszcze więcej czasu i wymaga dodatkowych zasobów. Innym często przeoczonym problemem z CGI jest niemoŜność interakcji programu CGI z serwerem WWW lub skorzystania z moŜliwości serwera po rozpoczęciu działania tego programu, poniewaŜ działa on jako osobny proces. Na przykład, skrypt CGI nie potrafi zapisywać informacji w dzienniku zdarzeń serwera. Większa ilość informacji na temat programowania CGI jest dostępna w ksiąŜce „CGI Programming on the World Wide Web” autorstwa Shishira Gundavarama (O'Reilly).
FastCGI Firma o nazwie OpenMarket stworzyła alternatywę dla standardu CGI o nazwie FastCGI. W większości aspektów, FastCGI działa podobnie do CGI — waŜną róŜnicą jest tworzenie przez FastCGI jednego trwałego procesu dla kaŜdego programu FastCGI, jak przedstawiono na rysunku 1.2. Eliminuje to konieczność tworzenia nowego procesu dla kaŜdego Ŝądania.
Rysunek 1.2. Okres trwałości FastCGI ChociaŜ FastCGI jest krokiem we właściwym kierunku, ciągle posiada on problem z mnoŜeniem się procesów — istnieje co najmniej jeden proces dla kaŜdego programu FastCGI. JeŜeli program FastCGI musi obsługiwać Ŝądania równoległe, potrzebuje puli procesów, jednego na kaŜde Ŝądanie. Pamiętając, Ŝe kaŜdy proces moŜe wykonywać interpretator Perla, podejście na to nie jest skalowalne na tyle, na ile moŜna się tego spodziewać. (ChociaŜ trzeba przyznać, Ŝe FastCGI moŜe rozkładać procesy pomiędzy wieloma serwerami.) Innym problemem z FastCGI jest to, Ŝe nie pozwala on swoim programom na bliŜszą interakcję z serwerem. Poza tym, programy FastCGI są przenośne jedynie tak, jak język, w którym zostały napisane. Większa ilość informacji na temat FastCGI jest dostępna pod adresem http://www.fastcgi.com.
PerlEx PerlEx, utworzony przez ActiveState, zwiększa wydajność skryptów CGI napisanych w Perlu pracujących na serwerach WWW pod Windows NT (Internet Information Server Microsoftu, Website Professional O'Reilly oraz FastTrack Server i Enterpise Server iPlanet). Posiada on zalety i wady podobne do FastCGI. Większa ilość informacji na temat PerlEx dostępna jest pod adresem http://www.activestate.com/plex.
mod_perl Przy korzystaniu z serwera WWW Apache, inną opcją zwiększenia wydajności CGI jest wykorzystanie mod_perl. mod_perl jest modułem serwera Apache osadzającym kopię interpretatora Perla w pliku wykonywalnym Apache'a, dostarczającym pełnej funkcjonalności Perla wewnątrz Apache'a. Jego efektem jest prekompilowanie skryptów CGI przez serwer i wykonywanie ich bez rozdzielania, a związku z tym ich praca jest duŜo szybsza i wydajniejsza. Jego wadą jest moŜliwość wykorzystania jedynie w serwerze Apache. Większa ilość informacji na temat mod_perl jest dostępna pod adresem http://perl.apache.org.
Inne rozwiązania CGI/Perl posiada zaletę bycia mniej lub bardziej niezaleŜnym od platformy sposobem na tworzenie dynamicznej zawartości WWW. Inne dobrze znane technologie tworzenia aplikacji WWW takie jak ASP i JavaScript działający po stronie serwera, są opatentowanymi rozwiązaniami pracującymi jedynie z określonymi serwerami WWW.
Interfejsy rozszerzeń serwera Kilka firm utworzyło własne interfejsy API rozszerzeń serwera dla swoich serwerów WWW. Na przykład, iPlanet/Netscape dostarcza wewnętrzny API o nazwie WAI (dawniej NSAPI), a Microsoft dostarcza ISAPI. Przy pomocy kaŜdego z tych interfejsów, moŜna utworzyć rozszerzenia serwera zwiększające lub zmieniające jego podstawową funkcjonalność, pozwalającą mu na obsługę zadań wcześniej delegowanych do zewnętrznych programów CGI. Jak moŜna dostrzec na rysunku 1.3, rozszerzenia serwera występują wewnątrz głównego procesu serwera WWW.
Rysunek 1.3. Okres trwałości rozszerzeń serwera PoniewaŜ specyficzne dla serwera interfejsy wykorzystują połączony kod C lub C++, rozszerzenia serwera działają niezwykle szybko i w pełni wykorzystują zasoby serwera. Nie są one jednak rozwiązaniem doskonałym. Poza tym, Ŝe są one cięŜkie w tworzeniu i utrzymaniu, stanowią powaŜne zagroŜenia dla bezpieczeństwa i niezawodności — załamanie rozszerzenia moŜe prowadzić do załamania całego serwera, złośliwe rozszerzenie moŜe kraść hasła uŜytkowników i numery kart kredytowych. Oraz, oczywiście konkretne rozszerzenia są nierozerwalnie związane z API serwera, dla którego zostały napisane, a takŜe do konkretnego systemu operacyjnego.
JavaScript działający po stronie serwera iPlanet/Netscape posiada równieŜ technikę skryptów działających po stronie serwera, nazywaną server-side JavaScript, w skrócie SSJS. Podobnie jak ASP, SSJS pozwala na osadzanie fragmentów kodu w stronach HTML w celu utworzenia dynamicznej zawartości WWW. RóŜnica jest taka, Ŝe SSJS wykorzystuje JavaScript jako język skryptowy. Z SSJS, strony są prekompilowane w celu poprawienia wydajności. Obsługa SSJS jest moŜliwa jedynie w serwerach iPlanet/Netscape. Większa ilość informacji na temat programowania przy pomocy JavaScript działającego po stronie serwera dostępna jest pod adresem http://developer.netscape.com/tech/javascript/ssjs/ssjs.html.
Active Server Pages Microsoft posiada technikę tworzenia dynamicznej zawartości WWW o nazwie Active Server Pages (Aktywne Strony Serwera), w skrócie ASP. Przy pomocy ASP, strona HTML moŜe zawierać fragmenty osadzonego kodu (zazwyczaj VBScript lub Jscript — chociaŜ moŜliwe jest zastosowanie niemal kaŜdego języka). Kod ten jest odczytywany i wykonywany przez serwer WWW przed wysłaniem strony do klienta. ASP został optymalizowany do tworzenia niewielkich porcji zawartości dynamicznej, większe pozostawiając składnikom COM. Obsługa ASP jest wbudowana w Internet Information Server Microsoftu w wersji 3.0 i wyŜszych, dostępnym bezpłatnie pod adresem http://www.microsoft.com/iis. Obsługa innych serwerów WWW jest dostępna jako komercyjny produkt firmy Chili!Soft pod adresem http://www.chilisoft.com. Proszę pamiętać, Ŝe strony ASP działające na platformie nie będącej Windows mogą mieć problemy z powodu braku biblioteki Windows COM. Większa ilość informacji na temat programowania ActiveServerPages jest dostępna pod adresem http://www.microsoft.com/workshop/server/default.asp oraz http://www.activeserverpages.com/.
JavaServer Pages JavaServer Pages, często nazywana po prostu JSP, jest opartą na Javie alternatywą dla ASP, utworzoną i wystandaryzowaną przez firmę Sun. JSP wykorzystuje składnię podobną do ASP poza tym, Ŝe językiem skryptowym w tym przypadku jest Java. Odwrotnie niŜ ASP, JSP jest otwartym standardem implementowanym przez wielu producentów na wszystkich platformach. JSP jest ścisłe związana z serwletami, poniewaŜ strona JSP jest przetwarzana do serwletu, co stanowi część jej wykonania. JSP jest bardziej szczegółowo opisana w dalszych częściach niniejszej ksiąŜki. Większa ilość informacji na temat JSP jest dostępna pod adresem http://java.sun.com/products/jsp.
Serwlety Javy W tym miejscu pojawiają się serwlety Javy. Jak wspomniano wcześniej, serwlet jest ogólnym rozszerzeniem serwera — klasą Javy, która moŜe być dynamicznie ładowana w celu rozszerzenia funkcjonalności serwera. Serwlety są często uŜywane w serwerach WWW, gdzie zajmują miejsce skryptów CGI. Serwlet jest podobny do poprzednio omawianego rozszerzenia serwera, poza tym, Ŝe działa on wewnątrz wirtualnej maszyny Javy (Java Virtual Machine — JVM) na serwerze (proszę spojrzeć na rysunek 1.4), tak więc są one bezpieczne i przenośne. Serwlety działają wyłącznie w domenie serwera — inaczej niŜ aplety, nie wymagają one obsługi Javy przez przeglądarkę WWW.
Rysunek 1.4. Okres trwałości serwletu Inaczej niŜ CGI i FastCGI, które muszą wykorzystywać wiele procesów w celu obsługi oddzielnych programów i/lub oddzielnych Ŝądań, serwlety mogą być obsługiwane przez osobne wątki w tym samym procesie, z wieloma procesami rozciągniętymi na klika serwerów wspierających. Oznacza to, Ŝe serwlety są równieŜ wydajne i skalowalne. PoniewaŜ serwlety działają z komunikacją dwustronną do serwera WWW, mogą bardzo ściśle współpracować z serwerem w celu wykonania działań niemoŜliwych dla skryptów CGI. Inną zaletą serwletów jest ich przenośność — zarówno pomiędzy systemami operacyjnymi jak w przypadku Javy, jak i pomiędzy serwerami WWW. Jak zostanie to opisane poniŜej, większość głównych serwerów WWW obsługuje serwlety. UwaŜa się, Ŝe serwlety stanowią najlepszą moŜliwą platformę dla tworzenia aplikacji WWW, a więcej informacji na ten temat zostanie podane w dalszej części tego rozdziału.
Obsługa serwletów Podobnie jak sama Java, serwlety zostały zaprojektowane w celu zapewnienia maksymalnej przenośności. Serwlety obsługiwane są przez wszystkie platformy obsługujące równieŜ Javę, oraz pracują w większości podstawowych serwerów WWW1. Serwlety Javy zdefiniowane przez dział Java Software firmy Sun Microsystems (dawniej znany jako JavaSoft), stanowią Pakiet Opcjonalny (Optional Package) dla Javy (dawniej znany jako Rozszerzenie Standardowe — Standard Extension). Oznacza to, Ŝe serwlety zostały oficjalnie pobłogosławione przez Sun'a i stanowią część języka Java, lecz nie są częścią podstawowego API Javy. Zamiast tego, są one znane jako część platformy J2EE. W celu ułatwienia tworzenia serwletów, Sun i Apache udostępniły klasy API niezaleŜnie od Ŝadnego mechanizmu WWW. Pakiety javax.servlet i javax.servlet.http składają się na Servlet API. Najnowsza wersja tych klas jest dostępna do pobrania pod adresem http://java.sun.com/products/servlet/download.html2. Wszystkie serwery WWW obsługujące serwlety muszą
1 Proszę zauwaŜyć, Ŝe niektórzy producenci serwerów WWW posiadają swoje własne implementacje Javy działającej po stronie serwera, niektóre z nich noszą równieŜ nazwę serwletów. Są one generalnie niekompatybilne z serwletami Javy utworzonymi przez Sun'a. Większość z tych producentów konwertuje swoją obsługę Javy do standardowych serwletów lub wprowadzają obsługę standardowych serwletów równolegle, w celu zapewnienia wstecznej kompatybilności. 2
W pewnym momencie planowano dołączenie tych klas do JDK 1.2. Później jednak zdecydowano na utrzymanie ich niezaleŜności od JDK w celu ułatwienia dokonywania poprawek do Servlet API.
wykorzystywać te klasy wewnętrznie (chociaŜ mogą stosować alternatywną implementację), tak więc generalnie ten plik JAR moŜe zostać znaleziony gdzieś wewnątrz dystrybucji serwera WWW obsługującego serwlety. Nie jest waŜne, skąd pobiera się klasy serwletów, naleŜy posiadać je jednak w swoim systemie w celu kompilowania serwletów. Dodatkowo konieczny jest program uruchamiający serwlety (technicznie nazywany kontenerem serwletów, czasami mechanizmem serwletów), w celu przetestowania i udostępnienia serwletów. Wybór kontenera serwletów zaleŜy po części od działającego w danym systemie serwera(ów) WWW. Istnieją trzy odmiany kontenerów serwletów — samodzielne, dołączane i osadzane.
Samodzielne kontenery serwletów Samodzielny kontener serwletów to serwer zawierający wbudowaną obsługę serwletów. Taki kontener posiada tę przewagę, Ŝe wszystko w nim działa niejako od razu. Jednak wadą jest konieczność oczekiwania na nową wersję serwera WWW w celu uzyskania obsługi najnowszych serwletów. Inną wadą jest takŜe fakt, Ŝe producenci serwerów generalnie obsługują jedynie JVM dostarczoną przez samych siebie. Serwery WWW dostarczające samodzielnej obsługi to między innymi:
3
•
Tomcat Server Apache, oficjalna wzorcowa implementacja sposobu obsługi serwletów przez kontener. Napisany całkowicie w Javie, dostępny bezpłatnie w licencji Open Source. Dostępny jest cały kod źródłowy i kaŜdy moŜe pomóc w jego tworzeniu. Serwer ten moŜe działać samodzielnie lub jako dodatek dostarczający obsługi serwletów Apache'owi lub innym serwerom. MoŜe być równieŜ wykorzystywany jako kontener osadzony. Równolegle z Tomcatem, Apache tworzy standardową implementację pakietów javax.servlet i javax.servlet.http. W trakcie pisania niniejszej ksiąŜki serwlety są jedynymi pakietami java.* lub javax.* utrzymywanymi jako Open Source3. Proszę zobaczyć http://jakarta.apache.org.
•
iPlanet Web Server Enterprise Edition Netscape'a (wersja 4.0 i późniejsze), przypuszczalnie najpopularniejszy serwer WWW zawierający wbudowaną obsługę serwletów. Niektóre testy wykazują, Ŝe posiada on najszybszą implementację serwletów. Proszę pamiętać, Ŝe chociaŜ wersje 3.51 i 3.6 zawierały wbudowaną obsługę serwletów, to jednak był to wczesny Servlet API 1.0 i zawierały one duŜą liczbę błędów tak powaŜnych, Ŝe obsługa serwletów była praktycznie bezuŜyteczna. W celu wykorzystania serwletów z serwerami Netscape'a w wersji 3.x naleŜy wykorzystać dołączany kontener. Proszę zobaczyć http://www.iplanet.com.
•
WebSite Professional O'Reilly, o podobnej funkcjonalności do Enterprise Server iPlanet, lecz za niŜszą cenę. Proszę zobaczyć http://website.oreilly.com.
•
Zeus Web Server, serwer WWW uwaŜany przez niektórych za najszybszy z dostępnych. Jego lista własności jest dość długa i zawiera obsługę serwletów. Proszę zobaczyć http://www.zeus.co.uk.
•
Resin Caucho, kontener Open Source, uwaŜany za bardzo wydajny. MoŜe być uruchamiany w trybie samodzielnym lub jako dodatek do wielu serwerów. Proszę zobaczyć http://www.caucho.com.
•
LiteWebServer Gefion Software, niewielki (nieco ponad 100 KB) kontener serwletów utworzony dla zastosowań, takich jak dołączanie do wersji demonstracyjnych, gdzie niewielki rozmiar ma znaczenie. Proszę zobaczyć http://www.gefionsoftware.com/LiteWebServer.
•
Jigsaw Server World Wide Web Consortium Open Source, napisany całkowicie w Javie. Proszę zobaczyć http://www.w3.org/Jigsaw.
•
Java Web Server firmy Sun, serwer, od którego wszystko się rozpoczęło. Serwer ten był pierwszym serwerem implementującym serwlety oraz działał jako efektywna wzorcowa implementacja dla Servlet API 2.0. Jest on napisany całkowicie w Javie (poza dwoma bibliotekami kodu macierzystego, które powiększają funkcjonalność, lecz nie są konieczne). Sun nie kontynuuje juŜ prac nad serwerem, koncentrując się na produktach iPlanet/Netscape w ramach sojuszu Sun-Netscape. Proszę zobaczyć http://java.sun.com/products.
Implementacja javax.servlet i javax.servlet.http w standardzie Open Source spowodowała naprawienie wielu błędów (na przykład, autor miał okazję poprawić obsługę warunkowego GET w HttpServlet) i kwestii niekompatybilności. Istnieje nadzieja, Ŝe przykład ten wspomoŜe w udostępnieniu większej ilości oficjalnych pakietów Javy jako Open Source
Serwery aplikacji są rosnącym obszarem tworzenia. Serwer aplikacji oferuje obsługę po stronie serwera dla tworzenia aplikacji korporacyjnych. Większość aplikacji opartych na Javie obsługuje serwlety i pozostałą część specyfikacji Java 2, Enterprise Edition (J2EE).Serwery te to miedzy innymi: •
WebLogic Application Server BEA System, jeden z pierwszych i najsłynniejszych opartych na Javie serwerów aplikacji. Proszę zobaczyć http://www.beasys.com/products/weblogic.
•
Orion Application Server, wysoko wydajny serwer o stosunkowo niskiej cenie, napisany całkowicie w Javie. Proszę zobaczyć http://www.orionserver.com.
•
Enhydra Application Server, serwer Open Source firmy Lutris. Proszę zobaczyć http://www.enhydra.org.
•
Borland Application Server 4, serwer ze specjalnym naciskiem na technologię CORBA. Proszę zobaczyć http://www.borland.com/appserver.
•
WebSphere Application Server IBM, wysokowydajny serwer oparty w części na kodzie Apache'a. Proszę zobaczyć http://www-4.ibm.com/software/webservers.
•
Dynamo Application Server 3 ATG, kolejny wysokowydajny serwer napisany całkowicie w Javie. Proszę zobaczyć http://www.atg.com.
•
Application Server Oracle, serwer zaprojektowany do integracji z bazą danych Oracle. Proszę zobaczyć http://www.oracle.com/appserver.
•
iPlanet Application Server, zgodny z J2EE większy brat iPlanet Web Server Enterprise Edition. Proszę zobaczyć http://www.iplanet.com/products/infrastructure/app_servers/nas.
•
GemStone/J Application Server, serwer Javy stworzony przez firmę poprzednio znaną z serwera Smalltalk. Proszę zobaczyć http://www.gemstone.com/products/j.
•
Jrun Server Allaire (poprzednio Live Software), prosty kontener serwletów, który rozrósł się do zaawansowanego kontenera dostarczającego wiele technologii J2EE włączając w to EJB, JTA i JMS. Proszę zobaczyć http://www.allaire.com/products/jrun.
•
Silverstream Application Server, w pełni zgodny z J2EE serwer, który rozpoczął równieŜ od skupienia się na serwletach. Proszę zobaczyć http://www.silverstream.com.
Dołączane kontenery serwletów Dołączany kontener serwletów działa jako moduł rozszerzający do istniejącego serwera — dodaje obsługę serwletów do serwera, który w oryginale nie był do tego przeznaczony, lub do serwera ze słabą lub nieaktualną implementacją serwletów. Dołączane kontenery serwletów zostały utworzone dla wielu serwerów, między innymi Apache'a, FastTrack Server i Enterprise Server iPlanet, Internet Information Server i Personal Web Server Microsoftu, Website O'Reilly, Go Webserver Lotus Domino, WebSTAR StarNine oraz AppleShare IP Apple. Dołączane kontenery serwletów to między innymi: •
ServletExec New Atlanta — moduł rozszerzający zaprojektowany do obsługi serwletów we wszystkich popularnych serwerach na wszystkich popularnych systemach operacyjnych. Zawiera bezpłatny program uruchomieniowy. Proszę zobaczyć http://www.servletexec.com.
•
Jrun Allaire (dawniej Live Software), dostępny jako moduł rozszerzający do obsługi serwletów we wszystkich popularnych serwerach na wszystkich popularnych systemach operacyjnych. Proszę zobaczyć http://www.allaire.com/products/jrun/.
•
Moduł Jserv projektu Java-Apache, bezpłatny kontener serwletów Open Source, który dodaje obsługę serwletów do niezwykle popularnego serwera Apache. Tworzenie Jserv zakończyło się, a Tomcat Server (działający jako moduł rozszerzający) jest jego następcą. Proszę zobaczyć http://java.apache.org/.
•
Tomcat Server Apache, jak opisano poprzednio. Tomcat moŜe być dołączony do innych serwerów takich jak Apache, iPlanet/Netscape i IIS.
Osadzane kontenery serwletów Osadzany kontener jest ogólnie niewielką platformą programistyczną, która moŜe być osadzana w innych aplikacjach. Aplikacja ta staje się prawdziwym serwerem. Osadzane kontenery serwletów to między innymi: •
Tomcat Server Apache, podczas gdy ogólnie uŜywany samodzielnie lub dołączany, moŜe być równieŜ osadzany w innej aplikacji, kiedy jest to potrzebne. PoniewaŜ serwer ten to Open Source, tworzenie większości innych osadzanych serwerów zatrzymano.
•
Nexus Web Server autorstwa Andersa Kristensena, dostępny bezpłatnie program uruchamiający serwlety, implementujący większą część Servlet API, który moŜe być w łatwy sposób dołączany do aplikacji Javy. Proszę zobaczyć http://www-uk.hpl.hp.com/people/ak/java/nexus/.
Uwagi dodatkowe Przed przejściem do następnej części naleŜy zapamiętać, Ŝe nie wszystkie kontenery serwletów są tworzone w jednakowy sposób. Tak więc przed wybraniem kontenera serwletów (i prawdopodobnie serwera) przy pomocy którego udostępniane będą serwlety, naleŜy go wypróbować, prawie do granic moŜliwości. Sprawdzić listy dystrybucyjne. NaleŜy zawsze sprawdzać, czy serwlety zachowują się tak, jak we wzorcowej implementacji Tomcata. MoŜna równieŜ sprawdzić, jakie narzędzia programistyczne są dostarczane, które technologie J2EE są wspierane i jak szybko moŜna uzyskać pomoc u producenta. W przypadku serwletów nie trzeba się martwić o zgodność z najsłabszą implementacją, tak więc naleŜy pobrać kontener serwletów, który posiada wszystkie poŜądane właściwości. Kompletna, aktualna lista dostępnych kontenerów serwletów razem z ich obecnymi cenami jest dostępna pod adresem http://www.servlets.com.
Potęga serwletów Jak dotychczas serwlety zostały opisane jako alternatywa dla innych technologii dynamicznej zawartości WWW, lecz nie zostało tak naprawdę powiedziane, dlaczego powinny być one, zdaniem autorów, stosowane. Co sprawia, Ŝe serwlety są jednym z najlepszych sposobów programowania WWW? Zdaniem autorów posiadają one kilka zalet ponad innymi podejściami, włączając w to przenośność, moc, wydajność, wytrzymałość, bezpieczeństwo, elegancję, integrację, rozszerzalność i elastyczność. KaŜda z tych własności zostanie kolejno omówiona.
Przenośność PoniewaŜ serwlety są pisane w Javie według dobrze zdefiniowanego i szeroko akceptowanego API, są one w duŜym stopniu przenośne pomiędzy systemami operacyjnymi i implementacjami serwerów. MoŜna stworzyć serwlet na komputerze pod Windows NT i z serwerem Tomcat, po czym bez problemu udostępnić go na wysoko wydajnym serwerze Uniksowym z iPlanet/Netscape Application Server. Stosując serwlety moŜna naprawdę „napisać raz, udostępniać wszędzie”. Przenośność serwletów nie jest tak waŜną sprawą jak w przypadku apletów, z dwóch powodów. Po pierwsze, przenośność serwletów nie jest obowiązkowa. Inaczej niŜ w przypadku apletów, które muszą zostać przetestowane na wszystkich moŜliwych platformach klientów, serwlety muszą pracować jedynie na serwerach, które są wykorzystywane do tworzenia i udostępniania. Dopóki nie sprzedaje się swoich serwletów, nie trzeba się martwić o kompletną przenośność. Po drugie, serwlety unikają najbardziej pełnej błędów i niespójnie zaimplementowanej części języka Java — Abstract Windowing Toolkit (AWT), który stanowi bazę graficznych interfejsów Javy, takich jak Swing.
Moc Serwlety mogą wykorzystywać pełną moc jądra API Javy — pracę w sieci i dostęp do URL-i, wielowątkowość, kompresję danych, łączność z bazami danych (JDBC), serializację obiektów, zdalne wywoływanie metod (RMI)
oraz integrację ze starymi programami (CORBA). Serwlety mogą równieŜ korzystać z platformy J2EE, która zawiera obsługę Enterprise JavaBeans (EJBs), transakcji rozproszonych (JTS), standaryzowanych wiadomości (JMS), wyszukiwania katalogów (JNDI) oraz zaawansowanego dostępu do baz danych (JDBC 2.0). Lista standardowych API dostępnych serwletom rośnie, czyniąc tworzenie aplikacji WWW szybszym, łatwiejszym i bardziej niezawodnym. Jako autor serwletów, moŜna wykorzystać dowolną z mnóstwa niezaleŜnych klas Javy i składników JavaBeans. Serwlety mogą uŜywać niezaleŜnego kodu w celu obsługi zadań takich jak wyszukiwanie według wyraŜeń regularnych, tworzenie wykresów danych, dostosowany dostęp do baz danych, zaawansowana praca w sieci, analiza składniowa XML oraz tłumaczenia XSLT. Serwlety są równieŜ sprawne w umoŜliwianiu komunikacji klient-serwer. Posiadając oparty na Javie aplet i oparty na Javie serwlet, moŜna wykorzystać RMI i serializację obiektu w komunikacji klient-serwer, co oznacza, Ŝe ten sam kod moŜna wykonać zarówno na maszynie klienta, jak i na serwerze. Wykorzystywanie po stronie serwera języków innych niŜ Java jest znacznie bardziej skomplikowane, jako Ŝe konieczne jest tworzenie swoich własnych protokołów do obsługi komunikacji.
Wydajność i wytrzymałość Wywoływanie serwletów charakteryzuje się bardzo wysoką wydajnością. Kiedy serwlet zostaje załadowany, pozostaje w pamięci serwera jako pojedynczy egzemplarz obiektu. Następnie serwer wywołuje serwlet do obsługi Ŝądania przy pomocy prostego wywołania metody. Inaczej niŜ w przypadku CGI, nie trzeba wywoływać procesu ani interpretatora, tak więc serwlet moŜe rozpocząć obsługę Ŝądania niemal natychmiast. Wielokrotne, równoległe Ŝądania są obsługiwane przez osobne wątki, tak więc serwlety są w wysokim stopniu skalowalne. Serwlety są obiektami z natury trwałymi. PoniewaŜ serwlet zostaje w pamięci serwera jako pojedynczy egzemplarz obiektu, automatycznie zachowuje swój stan i moŜe utrzymywać kontakt z zasobami zewnętrznymi, takimi jak połączenia z bazami danych. W innym przypadku przywrócenie połączenia mogłoby zabrać kilkanaście sekund.
Bezpieczeństwo Serwlety obsługują bezpieczne praktyki programowania na róŜnych poziomach. PoniewaŜ są one pisane w Javie, dziedziczą po niej silne bezpieczeństwo typów. Podczas gdy większość wartości w programie CGI, włączając w to element numeryczny taki, jak numer portu serwera, są traktowane jako łańcuchy, wartości w Servlet API są manipulowane przy pomocy ich naturalnych typów, tak więc numer portu serwera jest reprezentowany jako integer. Automatyczne zbieranie śmieci przez Javę i brak wskaźników oznaczają, Ŝe serwlety są generalnie bezpieczne od problemów z zarządzaniem pamięcią, takich, jak uszkodzone wskaźniki, niewłaściwe odwołania do wskaźników oraz uszczerbki pamięci. Serwlety mogą bezpiecznie obsługiwać błędy, dzięki mechanizmowi obsługi wyjątków lub kontrolerowi dostępu Javy. JeŜeli serwlet wykona dzielenie przez zero lub inne nieprawidłowe działanie, wyrzuca wyjątek, który moŜe być bezpiecznie wychwycony i obsłuŜony przez serwer, który zapisze błąd w dzienniku zdarzeń i przeprosi uŜytkownika. JeŜeli podobny wyjątek napotkałoby rozszerzenie serwera oparte na C++, przypuszczalnie nastąpiłoby załamanie serwera. Serwer moŜe chronić siebie w większym stopniu poprzez zastosowanie menedŜera bezpieczeństwa lub kontrolera dostępu Javy. Serwer moŜe wykonywać swoje serwlety pod ochroną dokładnego kontrolera dostępu który, na przykład wymusza politykę bezpieczeństwa zaprojektowaną do strzeŜenia przed złośliwym lub źle zaprojektowanym serwletem dąŜącym do zniszczenia systemu plików serwera.
Elegancja Elegancja kodu serwletów jest uderzająca. Kod serwletów jest czysty, obiektowy, modularny i zadziwiająco prosty. Jednym z powodów tej prostoty jest sam Servlet API, który zawiera metody i klasy obsługujące wiele rutynowych elementów programowania serwletów. Nawet zaawansowane operacje, takie jak obsługa cookies i śledzenie sesji, są rozkładane na odpowiednie klasy. Kilka bardziej zaawansowanych, lecz takŜe popularnych zadań zostało pozostawione poza API, i w tych przypadkach autorzy próbowali to naprawić i tak powstał zbiór przydatnych klas w pakiecie com.oreilly.servlet.
Integracja Serwlety są ściśle zintegrowane z serwerem. Ta integracja pozwala serwletowi na współpracę z serwerem w sposób niedostępny dla programów CGI. Na przykład, serwlet moŜe wykorzystywać serwer w celu przetłumaczenia ścieŜek plików, dokonania logowania, sprawdzenia uwierzytelnienia oraz wykonania odwzorowania typu MIME. Właściwe dla konkretnego serwera rozszerzenia mogą wykonać większość tej pracy, lecz proces ten jest zazwyczaj znacznie bardziej złoŜony i obfity w błędy.
Rozszerzalność i elastyczność Servlet API jest zaprojektowany w celu zapewnienia łatwej rozszerzalności. W obecnym czasie, API zawiera klasy z wyspecjalizowaną obsługą serwletów HTTP. Lecz w późniejszym okresie moŜe być ona rozszerzona i zoptymalizowana dla innego typu serwletów, czy to produkcji Suna, czy innej firmy. Jest równieŜ moŜliwe, Ŝe jego obsługa serwletów HTTP moŜe być dalej rozwijana. Serwlety cechują się równieŜ elastycznością w tworzeniu zawartości. Mogą tworzyć prostą zawartość przy pomocy wyraŜeń out.println(), lub generować skomplikowany zbiór stron przy pomocy mechanizmu szablonów. Mogą tworzyć stronę HTML przez traktowanie strony jako zestawu obiektów Javy, lub tworzyć stronę HTML przez wykonanie transformacji XML do HTML. Serwlety mogą być nawet łączone w celu utworzenia całkowicie nowych technologii takich jak JavaServer Pages. Nie wiadomo, do czego jeszcze zostaną wykorzystane.
W tym rozdziale: •
Podstawy HTTP
•
Interfejs API (Servlet API)
•
Tworzenie strony
•
Aplikacje WWW
•
Przejdźmy dalej
Rozdział 2.
Aplety Http — wprowadzenie Ten rozdział to krótki samouczek pisania i uruchamiania prostych apletów HTTP. Opisane tutaj zostanie jak wdroŜyć aplet do standardowej aplikacji WWW i jak skonfigurować jego zachowanie przy uŜyciu XML-owego deskryptora rozmieszczenia. W przeciwieństwie do pierwszej edycji niniejszej ksiąŜki, ten rozdział obecnej nie opisuje opartych na apletach plików dołączanych serwera (SSI) lub wiązania łańcuchowego oraz filtrowania apletu. Mimo tego, iŜ techniki te były bardzo przydatne oraz zostały umieszczone w serwerze WWW (Java Web Server), nie zostały zatwierdzone w specyfikacji apletu, (która ukazała się po pierwszej edycji niniejszej pozycji). SSI zostały zastąpione przez nowe techniki tworzenia plików dołączanych programu. Wiązanie łańcuchowe apletu zostało uznane za zbyt nieczytelne dla oficjalnego zatwierdzenia, mimo tego jest wielce prawdopodobne, Ŝe sama jego idea zostanie wykorzystana w Interfejsie API 2.3 (Servlet API 2.3) jako część oficjalnego mechanizmu ogólnego zastosowania przed i po — filtrującego.
Zwróćmy uwagę, iŜ moŜliwe jest ściągnięcie kodów dla kaŜdego z przykładów zamieszczonych w tym oraz innych rozdziałach tej ksiąŜki, zarówno w formie źródłowej jak i skompilowanej (jak zostało to opisane w przedmowie). JednakŜe, co się tyczy tego rozdziału, wydaje się, iŜ rzeczą najbardziej pomocną w nauce będzie zapisanie przykładów ręcznie (za pomocą klawiatury). Lektura tego rozdziału moŜe prowadzić do wniosku, iŜ niektóre zagadnienia zostały potraktowane zbyt ogólnie. Aplety to narzędzia dające wiele moŜliwości i czasem bywają skomplikowane, dlatego teŜ rozdział ten ma na celu wprowadzenie w ogólne zasady ich działania i zorientowania się w temacie. Czytelnik po lekturze niniejszej ksiąŜki będzie w stanie samodzielnie tworzyć najrozmaitsze aplety.
Podstawy HTTP Zanim przejdziemy do omawiania prostych apletów HTTP, musimy sprawdzić znajomość podstaw działania protokołu HTTP. Będąc doświadczonym w programowaniu w CGI (lub mając doświadczenie w tworzeniu stron WWW na serwerach) moŜna z powodzeniem pominąć czytanie tego podrozdziału. W takim przypadku korzystnym wydaje się zatrzymanie się na istotnych zagadnieniach metod GET i POST. JednakŜe będąc osobą stawiającą pierwsze kroki w tworzeniu stron WWW na serwerach, naleŜy przeczytać wspomniany materiał uwaŜnie, poniewaŜ zrozumienie dalszej części ksiąŜki wymaga znajomości protokołu HTTP. Protokół HTTP został szczegółowo omówiony w „Pocket Reference” Clintona Wong’a (wydawnictwo O’Reilly).
Zlecenia, odpowiedzi, nagłówki HTTP jest prostym, międzynarodowym protokołem. Klient, np. przeglądarka WWW składa zlecenie, serwer WWW odpowiada i dokonywana jest tzw. „obsługa zlecenia”. Kiedy klient składa zlecenie, pierwszą rzeczą którą wykonuje, jest komenda HTTP zwana metodą, za pomocą której serwer orientuje się jaki rodzaj zlecenia jest składany. Pierwszy wiersz zlecenia określa adres dokumentu (URL) oraz uŜywaną wersję protokółu HTTP. Oto przykład: GET/intro.html Http/1.0
W tym zleceniu chodzi o uzyskanie dokumentu o nazwie intro.html za pomocą wersji 1.0 HTTP. Po przesłaniu zlecenia klient moŜe przesłać informacje nagłówkową w celu dostarczenia serwerowi dodatkowych informacji o zleceniu, takich jak: jakie oprogramowanie jest uŜywane przez klienta oraz jaka forma informacji potrzebna jest klientowi do jej zrozumienia. Takie informacje nie odnoszą się bezpośrednio do tego, co było przedmiotem zlecenia, jednakŜe mogą być wykorzystane przez serwer w tworzeniu odpowiedzi. Oto dwa przykłady nagłówków zleceń: User-Agent : Mozilla/4.0 (compatabile; MSIE 4.0; Windows 95) Accept : image/gif, image/jpeg, text/*, */*
Nagłówek User-Agent dostarcza informacji o oprogramowaniu klienta, podczas gdy nagłówek Accept określa rodzaj nośnika (MIME) najkorzystniejszy dla klienta (nagłówki zleceń zostaną
omówione szerzej przy omawianiu apletów, w rozdziale 4 „Odczytywanie informacji”). Celem zaznaczenia końca sekcji nagłówkowej, po przesłaniu nagłówków, klient przesyła nie zapisany wiersz. JeŜeli wymaga tego uŜywana metoda, klient moŜe równieŜ przesłać inne dodatkowe dane, tak jak w przypadku metody POST, która zostanie zaraz omówiona. JeŜeli zlecenie nie zawiera Ŝadnych danych, to kończy się nie zapisanym wierszem. Po przesłaniu przez klienta zlecenia, serwer przetwarza je i przesyła odpowiedź. Pierwszy wiersz odpowiedzi zawiera wiersz statusu oraz jego opis. Oto przykład: HTTP/1.0 200 OK.
PowyŜszy wiersz statusu zawiera kod statusu 200, co oznacza Ŝe zlecenie zostało wykonane, stąd opis OK. Kolejny często spotykany kod to 404 z opisem Not Found (nie znaleziono), jak łatwo się domyśleć opis ten oznacza, Ŝe dokument nie został odnaleziony. W rozdziale 5 „Przesyłanie informacji HTML” zostały omówione najczęściej spotykane kody statusu oraz w jaki sposób moŜna je wykorzystać w apletach. Dodatek D „Kody statusu HTTP” zawiera kompletną listę kodów statusu HTTP. Po przesłaniu wiersza statusu serwer przesyła nagłówki odpowiedzi, które są informacją dla klienta taką jak np.: jakiego oprogramowania uŜywa serwer oraz nośnika informacji uŜytego do zapisania odpowiedzi serwera. Oto przykład: Date: Saturday, 23-May-00 03:25:12 GMT Server: Tomcat Web Server/3.2 MIME-version:1.0 Content-type: text/html Content-length: 1029 Last-modified: Thursday, 7-May-00 12:15:35 GMT
Nagłówek Server dostarcza informacji o oprogramowaniu serwera, nagłówek Content-type określa rodzaj rozszerzenia MIME odnośnie danych zawartych w odpowiedzi (nagłówki odpowiedzi zostaną omówione szerzej w rozdziale 5). Po nagłówkach serwer przesyła „czysty wiersz” celem zakończenia sekcji nagłówkowej. JeŜeli zlecenie zostało wykonane, Ŝądane dane są następnie przesyłane jako część odpowiedzi. W przeciwnym wypadku odpowiedź moŜe zawierać informację tekstową dla osoby obsługującej przeglądarkę, która będzie wyjaśniała dlaczego serwer nie mógł wykonać zlecenia.
Metody GET i POST Klient łącząc się z serwerem moŜe złoŜyć zlecenie w kilku róŜnych formach, zwanych metodami. Najczęściej uŜywane metody to GET i POST. Metoda GET słuŜy do uzyskiwania informacji (dokumentów, wykresów, informacji bez danych), podczas, gdy metoda POST została zaprojektowana z myślą o wysyłaniu informacji (numerów kart kredytowych, danych statystycznych lub informacji baz danych). Wykorzystując analogię elektronicznego biuletynu informacyjnego, GET słuŜy do czytania a POST do zamieszczania w nim tekstu. GET to metoda uŜywana do wprowadzania URL-u bezpośrednio do przeglądarki lub podczas klikania na hiperlink; jednakŜe zarówno metoda GET jak i POST mogą być uŜywane do dostarczania formularzy HTML. Mimo, iŜ metoda GET została zaprojektowana w celu odczytywania informacji, moŜe zawierać jako część zlecenia informacje własne, które dokładniej precyzują to zlecenie. MoŜe to być np. układ współrzędnych x,y dla wykresów. Takie informacje są przesyłane jako ciąg znaków dołączonych do URL-u w formie znanej ciągiem zapytań. Ten sposób zamieszczania dodatkowych informacji w URL-u umoŜliwia przesłanie strony e-mailem bądź utworzenie z niej zakładki.
PoniewaŜ zlecenia GET nie są przeznaczone do przesyłania duŜych partii informacji, niektóre serwery ograniczają długość URL-ów i ciągów zapytań do około 240 znaków. W metodzie POST uŜywana jest odmienna technika przesyłania informacji do serwera, poniewaŜ niekiedy metody tej uŜywa się do przesyłania większych partii informacji. Zlecenie złoŜone za pomocą metody POST przesyła bezpośrednio wszystkie informacje (nie ograniczone co do długości) w nim zawarte za pomocą połączenia gniazdowego jako część swego zlecenia HTTP. Klient nie jest informowany o tej zamianie, URL nie ulega w ogóle zmianie. W efekcie zlecenia POST nie mogą być ani zapisane jako zakładki, ani wysłane e-mailem, ani teŜ w niektórych przypadkach nie mogą być w ogóle powtórnie załadowane. Powód jest prosty — sytuacja taka wynika z odpowiedniego zaprojektowania — informacja jak np. numer naszej karty kredytowej, powinna być przesyłana do serwera tylko raz. Stosując metodę POST uzyskujemy dodatkowo pewien stopień zabezpieczenia przy przesyłaniu poufnych informacji, poniewaŜ dziennik zdarzeń, który zapisuje wszystkie zgłoszenia URL-ów, nie rejestruje danych metody POST. W praktyce uŜycie metod GET i POST odbiega od celu, dla którego zostały zaprojektowane. Powszechną praktyką przy składaniu długich parametryzowanych zleceń na informacje jest uŜycie POST zamiast GET w celu uniknięcia problemów związanych z nadmiernie długimi URL-ami. Metoda GET jest równieŜ często wykorzystywana do ładowania informacji przez proste formularze poniewaŜ, no cóŜ, po prostu da się to w ten sposób zrobić. PowyŜsze problemy nie są jednak aŜ tak dramatyczne, wystarczy tylko pamiętać, iŜ zlecenia GET (z powodu tego, iŜ mogą być w prosty sposób zamieniane na zakładki) mogą wywołać zmianę na serwerze, za którą odpowiedzialny będzie klient. Chodzi o to, Ŝe zlecenia GET nie powinny być uŜywane do składania zleceń, uaktualniania baz danych oraz do innych działań umoŜliwiających identyfikację klienta (w przypadku wystąpienia zmian na serwerze).
Pozostałe metody Http Poza GET i POST istnieje jeszcze wiele, rzadziej uŜywanych metod HTTP, takich jak na przykład metoda HEAD. Metoda ta jest uŜywana przez klienta tylko do uzyskiwania nagłówków odpowiedzi, w celu określenia rozmiaru dokumentu, czasu modyfikacji lub ogólnej dostępności. Inne metody to PUT — do zamieszczania dokumentów bezpośrednio na serwerze, DELETE — wykorzystywana do ich usuwania stamtąd. Dwie ostatnie metody nie współpracują ze wszystkimi serwerami z powodu skomplikowanych procedur. Metoda TRACE jest powszechnie uŜywana do usuwania błędów — umoŜliwia przesłanie klientowi dokładnej treści jego zlecenia. Metoda OPTIONS moŜe być uŜyta do zapytania serwera, z którymi metodami współpracuje lub jak dotrzeć do poszczególnych jego zasobów.
Interfejs API (Servlet API) Po zapoznaniu się z podstawami HTTP, moŜemy przejść do omówienia interfejsów API, których z kolei uŜywa się do tworzenia apletów HTTP, lub innych rodzajów apletów odpowiednich dla tej materii. Aplety uŜywają klas i interfejsów z dwóch pakietów: javax.servlet i javax.servlet.http. Pakiet javax.servlet zawiera klasy i współpracuje ze standardowymi protokołowo–niezaleŜnymi apletami. Klasy te są rozszerzane przez klasy w pakiecie
java.servlet.http w celu dodania funkcjonalności specyficznej dla HTTP. Pakiet najwyŜszej klasy nazywa się javax zamiast zwykłego java, aby zasygnalizować, iŜ Interfejs API jest
pakietem dodatkowym (uprzednio zwanym Standardowym Rozszerzeniem). KaŜdy aplet musi wdroŜyć interfejs javax.servlet. Większość apletów wdraŜa ten interfejs przez rozszerzenie jednej z dwóch specjalnych klas: javax.servlet.GenericServlet lub javax.servlet.http.HttpServlet. Aplet niezaleŜny protokołowo powinien być podrzędny do GenericServlet, a aplet HTTP powinien być podrzędny w stosunku do HTTPservlet, który sam jest podklasą GenericServlet z dodana funkcjonalnością HTTP. W przeciwieństwie do zwykłego programu Java, i dokładnie tak jak zwykły aplet, aplet wykonywany na serwerze nie zawiera metody main(). Zamiast tego pewne metody apletów wywoływane są przez serwer w procesie obsługi zleceń. Za kaŜdym razem, kiedy serwer wysyła zlecenie do apletu, wywołuje jego metodę service(). Standardowy aplet w celu poprawnej obsługi zlecenia powinien zignorować swoją metodę service(). Metoda service() akceptuje dwa parametry: obiekt zlecenia i obiekt odpowiedzi. Obiekt zlecenia informuje aplet o zleceniu, a obiekt odpowiedzi uŜywany jest do wysyłania odpowiedzi. Rysunek 2.1. ukazuje jak standardowy aplet obsługujący zlecenie.
Rysunek 2.1. Standardowy aplet obsługujący zlecenie
Aplet HTTP zwykle nie ignoruje metody service(), tylko metodę doGet() (do obsługi zleceń GET) i metodę doPost() (do obsługi zleceń POST). Aplet HTTP moŜe zignorować jedną z powyŜszych metod lub obie, w zaleŜności od tego, jaki jest typ zlecenia, które ma obsłuŜyć. Metoda service() HttpServlet obsługuje instalację oraz transfer do wszystkich metod doXXX(), dlatego właśnie zwykle nie powinna być ignorowana. Na rysunku 2.2 został ukazany sposób, w jaki aplet HTTP obsługuje zlecenia metod GET i POST.
Rysunek 2.2. Aplet HTTP obsługujący zlecenia GET i POST Aplet HTTP moŜe zignorować odpowiednio metody doPut() i doDelete() celem obsłuŜenia zleceń PUT i DELETE. JednakŜe aplety HTTP generalnie nie modyfikują metod doTrace() czy doOptions(). Dla nich prawie zawsze wystarczające są implementacje domyślne. Pozostałe klasy w pakietach javax.servlet i javax.servlet.http to w większości klasy wspomagające. Na przykład klasy ServletRequest i ServletResponse w javax.servlet umoŜliwiają dostęp do zleceń i odpowiedzi standardowych serwerów, natomiast klasy HttpServletRequest i HttpServletResponse w javax.servlet.http umoŜliwiają dostęp do zleceń i odpowiedzi HTTP. Pakiet javax.servlet.http zawiera równieŜ klasę HttpSession, która oferuje wbudowaną funkcjonalność śledzenia sesji oraz klasę Cookie, która pozwala na szybkie instalowanie i przetwarzanie cookies.
Tworzenie strony Najbardziej podstawowy typ apletu HTTP tworzy pełną stronę HTML. Taki aplet ma zwykle dostęp do takich samych informacji, co przesyłane do skryptu CGI oraz do pewnej partii innych. Aplet, który tworzy strony HTML moŜe zostać uŜyty do wykonywania wszystkich zadań, tych które obecnie są wykonywane przy pomocy CGI, jak np. przetwarzanie formularzy HTML, tworzenie listy z bazy danych, przyjmowanie zamówień, sprawdzanie zamówień, sprawdzanie identyfikacji, itd.
Pisanie „Hello World” Przykład 2.1 ukazuje aplet HTTP tworzący kompletną stronę HTML. Dla uproszczenia sprawy aplet ten ,za kaŜdym połączeniem się z nim za pomocą przeglądarki WWW, wyświetla napis „Hello World”.*
*Pierwszy przykład zarejestrowanego programu „Hello World” pojawił się w „A Tutorial Introduction to the Language B”, napisanym przez Braiana Kernighana w 1973. Dla tych z czytelników, zbyt młodych, by pamiętać, język B był prekursorem języka C. Więcej informacji o języku programowania B oraz link do tej ksiąŜki moŜna znaleźć na stronie: http://cm.bell-labs.com/who/dmr/bintro.html.
Przykład 2.1. Aplet, który wyświetla „Hello World” import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HellWorld extends HttpServlet
{
public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType ("text/html"); PrintWriter out = res.getWriter ( ); out.println(""); out.println("Hello World"); out.println ("") ; out.println (Hello World"); out.println (""); } }
PowyŜszy aplet rozszerza klasę HttpServlet oraz ignoruje odziedziczoną z niej metodę doGet(). Kiedy serwer WWW otrzymuje zlecenie GET z tego apletu, kaŜdorazowo wywołuje metodę doGet(), przekazując mu obiekty HttpServletRequest oraz HttpServletResponse. Obiekt HttpServletRequest reprezentuje zlecenie klienta. Obiekt ten daje apletowi dostęp do informacji o kliencie, parametrach zlecenia, nagłówkach HTTP przekazywanych razem ze zleceniem oraz inne. W rozdziale 4. omówione zostały wszystkie moŜliwości obiektu zlecenia. Dla tego przykładu moŜemy jednak je pominąć jako, ze niezaleŜnie od typu zlecenia aplet ten wyświetla „Hello World”. Obiekt HttpServletResponse reprezentuje odpowiedź apletu. Aplet moŜe wykorzystać ten obiekt do dostarczenia danych klientowi. Mogą to być dane róŜnego typu, typ ten jednak powinien być określony jako część odpowiedzi. Aplet moŜe równieŜ uŜyć tego obiektu do ustalenia nagłówków odpowiedzi HTTP. W rozdziałach 5. i 6 „Przesyłanie treści multimedialnej” zostało omówione wszystko co moŜe zrobić aplet jako część odpowiedzi. Nasz aplet ustala najpierw za pomocą metody setContentType() typ zawartości swojej odpowiedzi do text/html, standardowego typu zawartości MIME dla stron HTML. Następnie uŜywa metody getWriter() w celu odczytania PrintWriter, międzynarodowego odpowiednika PrintStream. PrintWriter przekształca kod UNICODE Javy na kodowanie specyficzne lokalnie. Dla kodowania lokalnego — angielskiego zachowuje się tak jak PrintStream. Aplet uŜywa wreszcie PrintWriter do wysłania swojego HelloWorld HTML do klienta.
Uruchamianie „Hello World” Do tworzenia apletów potrzebne są dwie rzeczy: pliki klasy interfejsu API, które uŜywane są w tłumaczeniu programu źródłowego na język wynikowy oraz pojemnik apletu np. serwer WWW, który uŜywany jest z kolei przy uruchamianiu apletów. Wszystkie popularne pojemniki apletów oferują pliki klasy Interfejsu API, więc moŜna spełnić oba warunki (potrzebne do tworzenia apletów) za jednym ładowaniem.
Istnieją dziesiątki parametrów dostępnych pojemników apletów dla wdraŜania apletów, kilkanaście z nich zostało zamieszczonych w rozdziale 1 „Wprowadzenie”. Dokonując wyboru serwera naleŜy pamiętać, Ŝe musi on współpracować z wersją 2.2 Interfejsu API (Servlet API 2.2) lub późniejszą. Wersja 2.2 była pierwszą wersją Interfejsu API, która zapewniała dostęp do aplikacji WWW, jak zostało to omówione w tym rozdziale. Aktualna lista pojemników apletów oraz tego do jakiego poziomu API zapewniają one dostęp i jest dostępna pod adresem: http://www.servlets.com. Tak więc zapytajmy, co naleŜy zrobić z naszym kodem, aby zadziałał w serwerze WWW? — to zaleŜy od rodzaju serwera. W przykładach zaprezentowanych w tej ksiąŜce występuje serwer „Apache Tomcat 3.2”, serwer implementacji odniesienia API, napisany całkowicie w Javie, dostępny pod adresem: http://jakarta.apache.org. Serwer „Tomcat” zawiera mnóstwo dokumentacji, w której jest wyjaśnione jego zastosowanie. W niniejszej ksiąŜce dlatego właśnie omówione zostaną tylko ogólne zasady dotyczące pracy z serwerem. PoniŜsze omówienia powinny być takŜe zgodne z innymi serwerami (niŜ „Tomcat”) jednakŜe nie moŜna tego zagwarantować. JeŜeli uŜywamy serwera „Apache Tomcat”, to powinniśmy umieścić kod źródłowy dla apletu w katalogu server_root/webapps/ROOT/WEB-INF/classes (gdzie server_root jest katalogiem , w którym zainstalowaliśmy nasz serwer), jest to standardowa lokalizacja plików klasy apletu. Powód, dla którego aplety występują w tym katalogu zostanie omówiony później w tym rozdziale. Kiedy juŜ mamy właściwie umiejscowiony kod źródłowy HelloWorld, musimy go skompilować. To zadanie moŜemy wykonać przy pomocy standardowego kompilatora javac (lub naszego ulubionego środowiska graficznego Javy). NaleŜy się tylko upewnić, Ŝe mamy pakiety javax.servlet i javax.servlet.http w naszej ścieŜce klasy. Pracując z serwerem „Tomcat”, wystarczy tylko zamieścić server_root/lib/servlet.jar (lub przyszły odpowiednik) gdzieś w naszej ścieŜce klasy. Nazwa pliku oraz lokalizacja zaleŜą od serwera, więc w razie problemów trzeba zajrzeć do dokumentacji serwera, z którym mamy do czynienia. JeŜeli wyświetlony zostanie komunikat informujący o błędzie taki jak np. Package javax.server not found in import, oznacza to, Ŝe pakiety apletów nie są odnajdywane przez nasz kompilator, naleŜy więc sprawdzić nasza ścieŜkę klasy i spróbować jeszcze raz. Teraz, kiedy juŜ skompilowaliśmy nasz pierwszy aplet, moŜemy uruchomić nasz serwer i wejść do apletu. Uruchomienie serwera nie jest rzeczą trudną, naleŜy uaktywnić skrypt startup.sh (lub plik startowy startup.bat w Windows) znajdujący się w katalogu server_root/bin. To powinno wystarczyć do uruchomienia naszego serwera, jeŜeli pracujemy w Solairs lub w Windows. W przypadku pracy na innych systemach operacyjnych moŜe zdarzyć się sytuacja, Ŝe będziemy musieli dokonać pewnych modyfikacji w skryptach startowych. W przypadku konfiguracji domyślnych, serwer oczekuje na porcie 8080. Istnieje wiele sposobów dostępu do apletów. Dla przykładu moŜemy zrobić to przez wyraźne wprowadzenie do URL-u nazwy klasy apletu. MoŜemy wprowadzić URL do swojej ulubionej przeglądarki:http://server:8080/servlet/HelloWorld. Wyraz server zamieniamy na nazwę naszego komputera — serwera lub na localhost — jeŜeli serwer jest na naszym lokalnym komputerze. Powinna zostać wyświetlona strona podobna do tej poniŜej.
Rysunek 2.3. Aplet „HelloWorld” JeŜeli aplet byłby częścią pakietu musiałby zostać umieszczony w server_root/webapps/ROOT/WEB-INF/package/name.HelloWorld. Nie wszystkie serwery zezwalają automatycznie na dostęp do apletów przez uŜycie rodzajowego przedrostka /servlet/. Funkcja ta moŜe zostać wyłączona ze względów bezpieczeństwa, aby zapewnić, Ŝe dostęp do apletów jest moŜliwy tylko przez określoną konfigurację URL-u, w czasie administrowania serwerem. W celu zapoznania się ze szczegółami wyłączania i załączania przedrostka /servlet/ naleŜy zapoznać się z dokumentacją serwera, na którym pracujemy.
Przetwarzanie danych formularzowych Aplet „HelloWorld” nie jest zbyt skomplikowany, przejdźmy więc do rzeczy bardziej zaawansowanych. Tym razem utworzymy aplet, który będzie pozdrawiał uŜytkownika jego imieniem (i nazwiskiem). Nie jest to rzecz specjalnie skomplikowana, potrzebny jest nam najpierw formularz HTML, który spyta uŜytkownika o jego imię i nazwisko. Następująca strona powinna być w tym celu wystarczająca:
Introductions
Pozwól Ŝe spytam, jak się nazywasz?
Na rysunku 2.4 został ukazany sposób, w jaki strona ta zostanie wyświetlona na stronie uŜytkownika.
Rysunek 2.4. Formularz HTML Formularz ten powinien znaleźć się w pliku HTML, w katalogu serwera document_root. Jest to miejsce, w którym serwer szuka plików statycznych. Dla serweru „Tomcat” katalog ten to server_root/webapps/ROOT. Dzięki umieszczeniu pliku w tym katalogu, moŜe być on dostępny bezpośrednio pod adresem: http://server:8080/form.html. Kiedy uŜytkownik przesyła ten formularz, jego imię (i nazwisko) jest przesyłane do apletu „Hello” poniewaŜ uprzednio zainstalowaliśmy atrybut ACTION celem wskazania ich apletowi. Formularz uŜywa metody GET, więc jakiekolwiek dane są dodawane do URL-u zlecenia jako pasmo zapytań. JeŜeli np. uŜytkownik wprowadzi imię, nazwisko „Inigo Montoya”, URL zlecenia będzie wyglądał następująco: http://server:8080/servlet/Hello?name=Inigo+Montoya. Przerwa pomiędzy imieniem a nazwiskiem jest wyjątkowo kodowana przez przeglądarkę jako znak „+”, poniewaŜ URL nie moŜe zawierać spacji. Obiekt apletu: HttpServletRequest umoŜliwia dostęp do danych formularzowych w paśmie zapytań. Na przykładzie 2.2 została ukazana zmodyfikowana wersja naszego apletu „Hello”, która uŜywa swojego obiektu zlecenia do odczytywania parametru name. Przykład 2.2. Aplet, który „wie” kogo pozdrawia import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Hello extends HttpServlet
{
public void doGet (HttpServletRequest req, HttpServletResponse res) throwsServletException, IOException { res.setContentType ("text/html"); PrintWriter out = res.getWriter ( ); String name = req.getParameter ("imię i nazwisko"); out.println(""); out.println("Hello, " + name + ""); out.println(" do hasła , deskryptora wdroŜenia, tak jak na przykładzie 3.8. Przykład 3.8. Ładowanie apletu przy rozruchu
ps
PrimeSearcher
PowyŜsze komendy „mówią serwerowi”, Ŝeby utworzył kopię PrimeSearcher pod rejestrowaną nazwą ps oraz Ŝeby zainicjował aplet podczas sekwencji uruchamiania serwera. Z apletem moŜna połączyć się wtedy na URL-u /servlet/ps. Zwróćmy uwagę, iŜ kopia apletu obsługująca URL /servlet/PrintWriter meSearcher nie jest ładowana przy rozruchu. Na przykładzie 3.8 znacznik jest pusty. Znacznik moŜe równieŜ zawierać dodatnią liczbę całkowitą, oznaczającą kolejność, w której aplet powinien być załadowany w odniesieniu do innych apletów kontekstu. Aplety z niŜszymi liczbami ładowane są przed tymi z liczbami większymi. Aplety z wartościami ujemnymi lub nie-całkowitymi mogą być ładowane w kaŜdym momencie sekwencji uruchamiania, dokładna kolejność zaleŜna jest wtedy od serwera. Dla przykładu, web.xml ukazany na przykładzie 3.9 gwarantuje, Ŝe first będzie załadowany przed second, podczas gdy anytime moŜe zostać załadowany w kaŜdym momencie rozruchu serwera. Przykład 3.9. PokaŜ moŜliwości apletu
first
First
10
second
Second
20
anytime
Anytime
Buforowanie podręczne po stronie klienta Do tej pory nauczyliśmy się, Ŝe aplety obsługują zlecenia GET przy pomocy metody doGet(). I jest to niemal prawda. Cała prawda, jednakŜe jest taka, Ŝe nie do kaŜdego zlecenia konieczne jest wywoływanie metody doGet(). Dla przykładu, przeglądarka WWW, która stale łączy się z PrimeSearcher będzie musiała wywołać doGet() tylko po tym jak wątek wyszukujący znajdzie nową liczbę pierwszą. Do tego czasu wszystkie wywołania doGet() generują po prostu stronę, którą uŜytkownik juŜ oglądał, stronę prawdopodobnie przechowywaną w pamięci podręcznej przeglądarki. To co jest na ten moment najbardziej potrzebne, to sposób w jaki aplet mógłby informować o zmianach w jego wydruku wyjściowym. I tutaj właśnie pomocne będzie omówienie metody getlastModified(). Większość serwerów zawiera, jako część swojej odpowiedzi, nagłówek Last-Modified, wtedy kiedy odsyła dokument. Przykład wartości nagłówka Last-Modified mógłby wyglądać w następujący sposób: Tue, 06-May-98 15:41:02 GMT
PowyŜszy nagłówek informuje klienta o tym, kiedy ostatnio została zmieniona strona. Informacja sama w sobie nie jest specjalnie wartościowa, jednak zyskuje na wartości w momencie kiedy przeglądarka powtórnie ładuje stronę. Większość przeglądarek WWW, podczas odnawiania strony, zawiera w swoich zleceniach nagłówek If-Modified-Since, którego struktura jest identyczna z nagłówkiem LastModified: Tue, 06-May-98 15:41:02 GMT
Nagłówek ten informuje serwer o czasie, w którym nagłówek Last-Modified strony, był po raz ostatni ładowany przez przeglądarkę. Serwer moŜe odczytać ten nagłówek oraz stwierdzić czy plik był zmieniany od określonego czasu. JeŜeli okaŜe się, Ŝe plik został zmieniony, serwer musi przesłać nową treść. JeŜeli okaŜę się, Ŝe plik nie uległ zmianie, wtedy serwer moŜe wysłać przeglądarce krótką odpowiedź, informującą ją o tym oraz o tym, Ŝe wystarczy powtórnie wyświetlić wersję dokumentu schowaną w schowku (ta odpowiedź to: kod stanu 304 Not Modified). Technika ta działa najlepiej w przypadku stron statycznych: serwer moŜe uŜyć systemu plików w celu sprawdzenia kiedy określony plik został zmodyfikowany po raz ostatni. JednakŜe dla treści tworzonej dynamicznie, takiej jaka jest odsyłana przez aplety, serwer potrzebuje dodatkowej pomocy. Jednak wszystko co moŜe zrobić to odtwarzać je bezpiecznie zakładając jednocześnie, Ŝe zawartość ulega zmianie z kaŜdym połączeniem, eliminując w ten sposób konieczność uŜycia nagłówków Last-Modified oraz If-Modified-Since. Dodatkową pomocą aplet moŜe słuŜyć poprzez implementację (wdroŜenie) metody getLastModified(). Aplet wdroŜy tą metodę, aby przesłać dane dotyczące czasu, w którym po raz ostatni zmienił swój wydruk wyjściowy. Serwery wywołują tą metodę dwa razy, pierwszy raz kiedy odsyłają odpowiedzi (w celu wstawienia nagłówka odpowiedzi Last-Modified). Drugi raz, podczas obsługi zleceń GET, które zawierają nagłówek If-Modified-Since, dzięki temu serwer moŜe odpowiedzieć w sposób inteligentny. JeŜeli czas odesłania przez getLastModified() jest taki sam, bądź wcześniejszy niŜ czas nadesłania nagłówka If-
Modified-Since, wtedy serwer przesyła kod stanu Not Modified. W przeciwnym wypadku serwer wywołuje metodę doGet() oraz odsyła wydruk wyjściowy apletu*.
Niektórym apletom moŜe sprawiać trudność ustalenie czasu ostatniej modyfikacji. Dlatego w takich sytuacjach najlepszym wyjściem jest uŜycie zachowania domyślnego „play-it-safe”. Większość apletów jednakŜe doskonale daje sobie z tym radę. RozwaŜmy przypadek apletu „bulletin board” („elektroniczny biuletyn informacyjny”), aplet taki moŜe zarejestrować i odesłać kiedy, po raz ostatni treść biuletynu została zmieniona. Nawet gdy ten sam aplet obsługuje kilka biuletynów, nadal moŜe przesyłać róŜne czasy modyfikacji, odpowiednie dla parametrów podanych w zleceniu. Oto metoda get-Last-Modified dla naszego przykładu PrimeSearcher, która przesyła czas znalezienia ostatniej liczby pierwszej: public long getLastModified(HttpServletRequest req) { return lastprimeModified.getTime() /1000 * 1000; }
Zwróćmy uwagę, iŜ metoda ta przesyła wartość długą, która przedstawia czas jako liczbę milisekund, która upłynęła od 1 stycznia 1970 roku GMT. Takiej samej reprezentacji uŜywa Java w celu przechowywania wartości czasowych. Dzięki temu aplet uŜywa metody getTime() do wczytania LastprimeModified() jako long. Aplet zanim odeśle tą wartość czasową, zaokrągla ją do najbliŜszej sekundy, dzieląc ją przez tysiąc a następnie mnoŜąc przez tysiąc. Wszystkie czasy odesłane przez getLastModified() powinny być zaokrąglone w ten sposób. Powodem tego jest fakt, Ŝe nagłówki Last-Modified oraz If-Modified-Since są przypisane do najbliŜszej sekundy. JeŜeli get-Last-Modified odeśle ten sam czas lecz z wyŜszą rozdzielczością, czas ten moŜe błędnie wydawać się parę milisekund późniejszy niŜ podany przez If-Modified-Since. ZałóŜmy dla przykładu, Ŝe PrimeSearcher znalazł liczbę pierwszą dokładnie 869.127.442.359 milisekund od wyŜ. wsp. daty. Fakt ten przekazywany jest przeglądarce lecz tylko do najbliŜszej sekundy: Thu, 17 – Jul – 97
09:17:22 GMT
Teraz załóŜmy znowu., Ŝe uŜytkownik powtórnie ładuje stronę i, Ŝe przeglądarka podaje serwerowi poprzez nagłówek If-Modified-Since, czas który uwaŜa za czas ostatniej modyfikacji: Thu, 17-Jul-97
09:17:22 GMT
Niektóre serwery przyjmują ten czas, przeliczają go na dokładnie 869 127 442 000 milisekundy, uznają iŜ jest on 359 milisekund wcześniejszy od odesłanego przez getLastModified(), a następnie fałszywie zakładają, Ŝe treść apletu uległa zmianie. Dlatego właśnie, Ŝeby zachować bezpieczeństwo („to play it safe”), getLastModified() powinna zawsze zaokrąglać do najbliŜszego tysiąca milisekund. Obiekt HttpServletRequest jest przekazywany do getLastModified() w razie jakby aplet potrzebował oprzeć swoje rezultaty na informacjach specyficznych dla określonego zlecenia. Standardowy aplet elektronicznego biuletynu informacyjnego moŜe to wykorzystać np. do określenia który biuletyn jest przedmiotem zlecenia.
*
Aplet moŜe wstawić bezpośrednio swój nagłówek LastModified, w doGet(), przy uŜyciu technik omówionych w rozdziale 5.(„Przesyłanie informacji HTML”). JednakŜe do czasu kiedy nagłówek zostanie wstawiony w doGet() jest juŜ zbyt późno by zdecydować o tym czy wywoływać doGet() czy nie.
Buforowanie zewnętrzne po stronie serwera Metoda getLastModified() moŜe, przy odrobinie pomysłowości, być pomocna w zarządzaniu pamięcią podręczną wydruku zewnętrznego apletu. Aplety stosujące taki chwyt mogą mieć swój wydruk zewnętrzny przechwycony i umieszczony w pamięci podręcznej na stronie serwera, a następnie odesłany do klientów jak to ma miejsce przy metodzie getLastModified(). Taka procedura moŜe znacznie przyspieszyć tworzenie strony apletu, szczególnie w przypadku apletów, którym zajmuje duŜo czasu tworzenie wydruku wyjściowego, zmieniającego się rzadko, takich jak np. aplety wyświetlające dane z bazy danych. Celem wdroŜenia buforowania zewnętrznego po stronie serwera, aplet musi: •
Rozszerzyć com.oreilly.servlet.CacheHttpServlet zamiast HttpServlet
•
WdroŜyć metodę getLastModified (HttpServletRequest)
Przykład 3.10 ukazuje aplet korzystający z CacheHttpServlet. Jest to księga gości apletu, która wyświetla przedłoŜone przez uŜytkowników komentarze. Aplet przechowuje komentarze uŜytkowników w pamięci jako obiekty Vector of GuestbookEntry.W rozdziale 9 „Dołączalność bazy danych” poznamy wersję tego apletu działającą poza bazą danych. W celu stymulacji czytania z wolnej bazy danych, pętla wyświetlacza ma pół-sekundowe opóźnienie na hasło. Im dłuŜsza lista haseł tym wolniejsza wizualizacja strony. JednakŜe z powodu tego, Ŝe aplet rozszerza CacheHttpServlet, wizualizacja musi mieć miejsce tylko podczas pierwszego zlecenia GET, po dodaniu nowego komentarza. Wszystkie późniejsze zlecenia GET wysyłają odpowiedź z pamięci podręcznej. Przykładowy wydruk wyjściowy został pokazany na rycinie 3.4. Przykład 3.10. Lista gości uŜywająca apletu „CacheHttpServlet” import import import import import
java.io.*; java.util.*; javax.servlet.*; javax.servlet.http.*; com.oreilly.servlet.CacheHttpServlet;
public class Guestbok
extends HttpServlet {
private Vector entries = new Vector(); // Lista haseł uŜytkownika private long lastModified = 0; // Czas, w którym zostało // dodane ostatnie hasło // Wyświetl aktualne hasła, następnie poproś out.println nowe hasło public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType ("text / zwykły"); PrintWriter out = res.getWriter(); printHeader(out); printForm(out); printMassages(out); printFooter(out); } // Dodaj nowe hasło, następnie odeślij z powrotem do doGet()
public void doPost (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { handleForm(req, res); doGet(req, res); } private void printHeader(PrintWriter out) throws ServletException { out.println ("
wml
text /vnd. wap. wml
wmls
text /vnd. wap. wmlscript
wbmp
image /vnd. wap. wbmp
< /mime-mapping>
index.html
index.htm
index.wml
Znacznik utrzymuje wartość limitu czasu (terminu waŜności) podaną w minutach. Dla przykładu, ustaliliśmy, Ŝe jeŜeli uŜytkownik nie złoŜy Ŝadnego zlecenia do aplikacji WWW, wtedy serwer moŜe uniewaŜnić sesję uŜytkownika i „rozwiązać” obiekty w niej przechowywane. Specyfikacja apletu wymaga, aby wartość terminu waŜności wyraŜona była liczbą całkowitą, co wyklucza wartości ujemne, jednak niektóre serwery uŜywają takich wartości, aby zasygnalizować, Ŝe sesja nigdy nie ulegnie przeterminowaniu.
Wartości limitu czasu mogą być równieŜ dla sesji konfigurowane indywidualnie. Obiekt HttpSession dysponuje metodą setMaxInactivateInterval() do takiego precyzyjnego sterowania: public void HttpSession.setMaxInactiveInterval(int secs)
Metoda ta określa wartość terminu waŜności dla sesji, podanego w sekundach. Wartość ujemna przedziału oznacza iŜ sesja nie ulegnie nigdy przeterminowaniu. Tak, jednostki nie pokrywają się z tymi ze znacznika , nie jest to niczym uwarunkowane, jest to po prostu przypadek. Aby łatwiej zapamiętać, które jednostki naleŜy zastosować, stosujmy następujący schemat myślenia: „Dla precyzyjnej kontroli uŜywamy precyzyjnych jednostek”. Aktualna (bieŜąca) wartość limitu czasu moŜe być uzyskana przy wykorzystaniu metody getMaxInactiveInterval(): public int HttpSession.getMaxInactiveInterval()
Metoda ta odsyła wartość terminu waŜności dla kaŜdej sesji, w sekundach. JeŜeli nie określimy znacznika moŜemy wywołać tą metodę na nową sesję, aby określić domyślny limit czasu naszego serwera. Na przykładzie 7.6 zaprezentowaliśmy omawiane metody, w aplecie, który wyświetla bieŜącą wartość limitu czasu, a następnie ustawia nową wartość terminu waŜności na dwie godziny. Podczas pierwszego wywołania, bieŜąca wartość limitu czasu wyświetla ogólno-aplikacyjne ustawienia. Podczas drugiego wywołania aktualny limit czasu wyświetla dwie godziny — poniewaŜ jest to limit czasu ustawiony podczas pierwszego wywołania.
Przykład 7.6. Ustawianie terminu waŜności import import import import
java.io.*; java.util.*; javax.servlet.*; javax.servlet.http.*;
public class SessionTimer extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IQException { res.setContentType("tekst/html") ; PrintWriter out = res.getWriter(); // Pobierz aktualny obiekt sesji, w razie konieczności utwórz go HttpSession session = req.getSession(); out.println("SessionTimer") ; out.println("Session Timer") ; // Wyświetl poprzedni termin waŜności out.println("Poprzedni termin waŜności to " + session. getMaxInactiveInterval ()) ; out.println("
") ; // Ustaw nowy termin waŜności session.setMaxInactiveInterval(2*60*60); // dwie godziny // Wyświetl nowy termin waŜności out.println("Nowo ustalony termin waŜności to " + session.getMaxInactiveInterval()) ; out.println("") ; } }
Wybieranie właściwego terminu waŜności Tak więc znamy, na ten moment, kilka sposobów na kontrolowanie terminu waŜności sesji, lecz jaka wartość limitu czasu jest najlepsza? Odpowiedź brzmi: to (oczywiście) zaleŜy. Pierwszą sprawą, którą trzeba zapamiętać, jest fakt iŜ wartość limitu czasu sesji nie determinuje jak długo sesja będzie trwała. Limit ten determinuje tylko jak długo będzie czekał z uniewaŜnieniem sesji pomiędzy zleceniami. Sesje z półgodzinnym limitem czasu mogłaby trwać godzinami. Określenie prawidłowego okresu bez-aktywności musi być kompromisem pomiędzy wygodą uŜytkownika, jego bezpieczeństwem a jego skalownością. DłuŜsze terminy waŜności dają uŜytkownikowi większą wygodę, poniewaŜ moŜe on robić dłuŜsze przerwy pomiędzy zleceniami, uzyskując czas aby np. wykonać telefon lub aby sprawdzić pocztę elektroniczną — bez utraty stanu. Krótsze limity czasu zwiększają bezpieczeństwo uŜytkownika, poniewaŜ ograniczają czas wraŜliwości (jeŜeli uŜytkownik np. zapomniał się wylogować) jednocześnie zwiększają skalowalność serwera, jako Ŝe serwer moŜe wtedy uwolnić obiekty w sesji duŜo wcześniej. Na wstępie zadajmy sobie pytanie jaki jest maksymalny czas oczekiwania naszego uŜytkownika pomiędzy zleceniami? Zwykle odpowiedź brzmi: pół godziny. RozwaŜmy sobie tą odpowiedź i poznajmy parę niezmiennych zasad: •
Bezpieczne aplikacje WWW, takie jak bankowość „on line”, powinny mieć krótsze niŜ zwykłe limity czasu aby umoŜliwić serwerowi odzyskanie lub „wypuszczenie” artykułów tak szybko jak to moŜliwe.
•
Sesje nie przechowujące „kosztownych” artykułów, mogą mieć dłuŜsze niŜ zwykłe terminy waŜności.
•
Sesje przechowujące zawartości koszyków zakupów (kosztowne lub nie) powinny mieć dłuŜsze limity czasu, poniewaŜ moŜe się zdarzyć, Ŝe uŜytkownicy nie będą pamiętali zawartości swych koszyków zakupów, co, w przypadku wczesnego uniewaŜnienia, oznaczałoby dla nas koszty finansowe!
•
Sesje przechowujące w pamięci podręcznej informacje bazy danych powinny mieć, w przypadku gdy pamięć podręczna ma duŜą objętość, krótsze terminy waŜności, jednak terminy te powinny być dłuŜsze dla tych sesji jeŜeli połączenie z bazą danych jest wyjątkowo wolne.
•
JeŜeli wymagamy od naszych uŜytkowników, aby wylogowywali się kiedy kończą pracę, domyślny limit czasu moŜe być ustawiony na dłuŜszy.
Pamiętajmy równieŜ, iŜ termin waŜności nie musi być taki sam dla kaŜdego uŜytkownika. W celu ustawienia własnego limitu czasu, opartego na preferencjach uŜytkownika lub nawet w celu jego zmiany w czasie trwania sesji — np. aby uczynić limit czasu krótszym po przechowywaniu „kosztownego” artykułu, moŜemy posłuŜyć się metodą setMaxInactiveInterval().
Metody czasu trwania Istnieje wiele dodatkowych metod związanych z obsługą czasu trwania sesji: public boolean HttpSession.isNew()
Metoda ta odsyła informację odnośnie tego czy sesja jest nowa czy nie. Sesja jest uznawana za nową, jeŜeli została utworzona przez serwer, lecz klient nie potwierdził jeszcze połączenia z nią. public void HttpSession.invalidate()
Metoda ta powoduje, iŜ sesja jest natychmiast uniewaŜniana. Wszystkie obiekty przechowywane w sesji zostają „rozwiązane”. Metodę tą wywołuje się w celu wdroŜenia wylogowania. public long HttpSession.getCreationTime()
Metoda ta odsyła czas, w którym sesja została utworzona, jako wartość long reprezentującą liczbę milisekund, która upłynęła od północy, 1 stycznia, 1970, czasu GMT. public long HttpSession.getLastAccessedTime()
Metoda ta odsyła czas, w którym klient przesłał ostatnie zlecenie związane z sesją, jako wartość long reprezentującą liczbę milisekund, która upłynęła od północy, 1 stycznia, 1970 roku. BieŜące zlecenie nie jest uznawane jako ostatnie. KaŜda z metod moŜe zgłosić wyjątek java.lang.IllegalStateException w przypadku gdy sesja, do której uzyskiwany jest dostęp jest niewaŜna.
„Ręczne” uniewaŜnianie starej sesji Aby zademonstrować działanie omawianych metod, na przykładzie 7.7 został zaprezentowany aplet „ręcznie” uniewaŜniający sesję — jeŜeli istnieje ona dłuŜej niŜ jeden dzień lub jeŜeli nie była aktywna przez okres dłuŜszy niŜ jedną godzinę.
Przykład 7.7. UniewaŜnianie starej sesji import import import import public
java. io. *; java.uti1.*; javax.servlet.*; javax.servlet.http.*; class ManualInvalidate extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("tekst/html") ; PrintWriter out = res.getWriter() ; // Pobierz bieŜący obiekt sesji, w razie konieczności utwórz go HttpSession session = reg.getSession() ; UniewaŜnij sesję, jeŜeli istnieje dłuŜej niŜ jeden dzień lub nie była // aktywna dłuŜej niŜ jedną godzinę. if (! session. isNew()) { // pomiń nowe sesje Date dayAgo = new Date(System.currentTimeMillis() - 24*60*60*1000); Date hourAgo = new Date (System.currentTiineMillis () 60*60*1000); Date created = new Date (session.getCreationTime ()); Date accessed = new Date (session.getLastAccessedTtme ()); if (created.before(dayAgo) || accessed.before(hourAgo)) { session.invalidate() ; session = reg.getSession() ; // pobierz nową sesję } } // Kontynuuj przetwarzanie } }
Zasada działania sesji Tak więc zastanówmy się jak serwer WWW wdraŜa śledzenie sesji? Kiedy uŜytkownik po raz pierwszy uruchamia aplikację WWW, jest mu przypisywany nowy obiekt sesji HttpSession oraz niepowtarzalna identyfikacja sesji (ID sesji). ID sesji identyfikuje uŜytkownika i jest wykorzystywana do dopasowania uŜytkownika z obiektem HttpSession w kolejnych zleceniach. Niektóre serwery wykorzystują pojedynczą identyfikację sesji dla całego serwera, z kaŜdą aplikacją WWW odwzorowującą to ID do innej kopii HttpSession. Z kolei inne serwery przypisują jedną identyfikację sesji do jednej aplikacji WWW, jako dodatkowe zabezpieczenie przed złośliwymi aplikacjami WWW, pomagającymi intruzowi w „zdepersonalizowaniu” nas.
W tle, ID sesji jest zwykle zapisywane po stronie klienta w cookie zwanym JSESSIONID. Dla klientów, którzy nie obsługują „Ciasteczek”, identyfikacja sesji moŜe zostać przesłana jako część przepisanego URL-u, zakodowanego przy uŜyciu parametru ścieŜki jsessionid, np. http://www.servlets.com/catalog/servlet/ItemDisplay;jsession=123?item=156592391X. Inne implementacje, takie jak wykorzystanie SSL — protokołu bezpiecznej transmisji danych sesji, są równieŜ moŜliwe. Aplet moŜe poznać ID sesji za pomocą metody getId(): public String HttpSession.getId()
Metoda ta odsyła niepowtarzalny identyfikator String, przypisany do sesji. Dla przykładu, ID serwera „Tomcat” mogłoby wyglądać w następujący sposób awj4gyhsn2. Metoda zgłasza wyjątek IllegalStateException w przypadku gdy sesja nie jest waŜna.
Pamiętajmy, iŜ identyfikacja sesji powinna być traktowana jako tajna informacja serwera. Zwracajmy uwagę na to, co robimy z tą wartością.
Wycofanie Obiektu HttpSessionContext W Interfejsie API 2.0 istniał obiekt HttpSessionContext, który był wykorzystywany do „tropienia” aktualnych sesji (oraz odpowiadającym im ID sesji), wykonywanych przez serwer. Prawie zawsze klasa była wykorzystywana do „debagowania” i sprawdzania jakie sesje jeszcze istnieją. Klasa ciągle jeszcze istnieje — dla zachowania kompatybilności binarnej, jednak począwszy od wersji 2.1 Interfejsu API, jest wycofana i określana jako pusta. Powodem jest fakt, iŜ identyfikacje sesji muszą być pilnie strzeŜone, więc nie powinny być przechowywane w łatwo dostępnej, pojedynczej lokalizacji, zwłaszcza jeŜeli istnienie takiej lokalizacji nie daje Ŝadnych znaczących korzyści, poza „debagowaniem”.
Apletowe śledzenie sesji Niemal kaŜdy serwer obsługujący aplety wdraŜa śledzenie sesji oparte na „Ciasteczkach”, gdzie identyfikacja sesji jest zapisywana po stronie klienta w trwałym cookie. Serwer odczytuje ID sesji z cookie JSESSIONID, a następnie determinuje który obiekt sesji uczynić dostępnym podczas kaŜdego zlecenia. Dla klientów apletu taka sytuacja moŜe przedstawiać problem. Większość środowisk apletowych wdraŜa HttpURLConnection w taki sposób, Ŝe kiedy aplet tworzy połączenie HTTP, środowisko automatycznie dodaje zawierające cookies przeglądarki, do zlecenia. Pozwala to apletowi na uczestniczenie w tej samej, co inne zlecenia przeglądarki, sesji. Problemem jest jednak, iŜ inne środowiska apletowe, takie jak starsze wersje środowiska „Java Plug-In enviroment” nie są zintegrowane z przeglądarką i dlatego zlecenia apletów jawią się jako oddzielone od normalnej sesji przeglądarki. Rozwiązanie dla sytuacji, w której aplety muszą działać w podobnych środowiskach jest przesyłane identyfikacji sesji do apletu oraz pozwalanie apletowi na przekazanie
tego ID z powrotem do serwera, jako sztucznie utworzone cookie JSESSIONID. W rozdziale 10 „Komunikacja aplet zwykły — aplet tworzony na serwerze” została zamieszczona klasa HttpMessage — aby pomagać w tego typu sytuacjach. Aplet moŜe otrzymać identyfikację sesji jako zwykły parametr apletu (dodany dynamicznie do strony HTML zawierającej aplet).
Awaryjne zmiany trybu pracy — „nie-ciasteczkowe” Specyfikacja apletu mówi, iŜ serwery WWW muszą obsługiwać śledzenie sesji równieŜ dla przeglądarek, które nie akceptują cookies, których tak wiele wykorzystuje przepisywanie URL-u jako awaryjną zmianę trybu pracy. Wymaga to dodatkowej pomocy ze strony apletów, które generują strony zawierające URL-e. W celu obsłuŜenia śledzenia sesji poprzez przepisywanie URL-u, aplet musi przepisać kaŜdy lokalny URL, zanim odeśle go klientowi. Interfejs API zawiera dwie metody, aby wykonać to zadanie: encode() oraz encodeRedirectURL():
public String HttpServlrtresponse.encodeURL(String url)
Metoda ta koduje (przepisuje) określony URL aby dołączyć ID sesji, a następnie odsyła nowy URL lub, jeŜeli kodowanie nie jest potrzebne albo nie obsługiwane, pozostawia URL niezmienionym. Zasady decydujące o tym kiedy i jak ma być zakodowany URL są domeną serwera. Wszystkie URL-e wychodzące z serwera, powinny być uruchamiane poprzez tą właśnie metodę. Zwróćmy uwagę, iŜ metoda encodeURL() mogłaby być bardziej precyzyjnie nazwana rewriteURL() — aby nie myliła się z procesem kodowania URL-u, który koduje specjalne znaki w strumieniu URL-u.
public String HttpServlrtresponse.encodeRedirectURL(String url)
Metoda ta koduje (przepisuje) określony URL aby dołączyć identyfikację sesji, a następnie odsyła nowy URL lub, jeŜeli kodowanie nie jest potrzebne albo nie obsługiwane — pozostawia URL niezmienionym. Zasady decydujące o tym kiedy i jak ma być zakodowany URL są domeną serwera. Metoda ta moŜe uŜywać odmiennych zasad niŜ metoda encodeURL(). Wszystkie URL-e przekazane do metody HttpServletResponse — sendDirect(), powinny być uruchamiane poprzez tą metodę.
PoniŜszy fragment kodu ukazuje aplet piszący łącznik do samego siebie, który jest kodowany tak, aby zawierał bieŜącą identyfikację sesji: out.println("Click here"); out.println("aby powtórnie załadować tą stronę.");
Na serwerach, które nie obsługują przepisywania URL-u lub mają wyłączoną tą funkcję, końcowy URL pozostaje bez zmian. PoniŜej przedstawiamy fragment kodu, na którym jest zaprezentowany aplet przekierowujący uŜytkownika do URL-u zakodowanego tak, aby zawierał ID sesji:
res.sendRedirect(res.encodeRedirectURL("/servlet/NewServlet")) ;
Aplet jest w stanie wykryć czy identyfikacja sesji, wykorzystywana do zidentyfikowania aktualnego obiektu HttpSession, pochodzi od cookie czy od zakodowanego URL-u wykorzystującego metody isRequestedSessionIdFromCookie() i isRequestedSessionIdFromURL(): public boolean HttpServletRequest.isRequestedSessionIdFromCookie() public boolean HttpServletRequest.isRequestedSessionIdFromURL()
Określenie czy identyfikacja sesji pochodzi z innego źródła, takiego jak sesja SSL, nie jest aktualnie moŜliwe.
ID sesji będące przedmiotem zlecenia moŜe nie pokrywać się z identyfikacją sesji, odesłaną przez metodę getSession(), tak jak ma to miejsce kiedy ID sesji jest niewaŜne. Aplet moŜe jednak ustalić czy identyfikacja sesji będąca przedmiotem zlecenia jest waŜna, przy pomocy metody isRequestedSessionIdValid(): public boolean HttpServletRequest.isRequestedSessionIdValid()
Miejmy równieŜ świadomość, iŜ kiedy uŜywamy śledzenia sesji opartego na przepisywaniu URLu, wielokrotne okna przeglądarki mogą naleŜeć do róŜnych sesji lub do tej samej sesji, w zaleŜności od tego w jaki sposób okna te zostały utworzone oraz czy tworzący je łącznik miał zastosowane przepisywanie URL-u.
Aplet „SessionSnoop” Zaprezentowany na przykładzie 7.8 aplet SessionSnoop wykorzystuje większość opisanych w rozdziale metod, aby „podsłuchać” informację o aktualnej sesji. Rysunek 7.3 prezentuje przykładowy wydruk wyjściowy apletu.
Przykład 7.8. „Podsłuchiwanie” informacji sesji import import import import
java.io.*; java.util.*; javax.servlet.*; javax.servlet.http.*;
public class SessionSnoop extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("tekst/html");
PrintWriter out = res.getWriter() ; // Pobierz aktualny obiekt sesji, w razie konieczności utwórz go HttpSession session = req.getSession(); // Zwiększ o jeden liczbę wejść na tą stronę. Wartość jest zapisana // w sesji klienta pod nazwą "snoop.count". Integer count = (Integer)session.getAttribute("snoop.count"); if (count == null) count = new Integer(1); else count = new Integer(count.intValue() + 1) ; session.setAttribute("snoop.count", count) ; out.println("SessionSnoop"); out.println("Session Snoop"); // Wyświetl ilość wejść na tą stronę out.println("Odwiedziłeś juŜ tą " + count + ((count.intValue() == 1) ? " raz." : " razy.")); out.println("
") ; out.println("Oto twoje zachowane dane sesji:"); Enumeration enum = session.getAttributeNames(); while (enum.hasMoreElements()) { name = (String) enum.nextElement(); intln (name + ": " + session.getAttribute (name) + ""); } out.println("Oto parę waŜniejszych stanów twojej sesji:"); out.println("ID sesji: " + session.getid() + " (keep it secret )
"); out.println("Now sesja: " + session.isNew() + "
"); out.println("Termin waŜności: " + session.getMaxInactiveInterval()); out.println("(" + session.getMaxInactiveInterval() / 60 + " minut) < / Ix>
") ; out.println("Czas utworzenia: " + session. getCreationTime() ); out. println ("(" + new Date (session.getCreationTime ()) + ")>
") ; out.println("Ostatni czas wejścia: " + session.getLastAccessedTime()); out.println("(" + new Date(session.getLastAccessedTime()) + ")
") ; out.println("ID sesji będące przedmiotem zlecenia z URL: " + req. isRequestedSessionIdFromURL () + "
") ; out.println("ID sesji, będące przedmiotem zlecenia jest waŜne: " + req.isRequestedSessionIdValid() + "
"); out.println("Test URL Rewriting"); out.println("Kliknij here") ; out.println("Aby sprawdzić czy śledzenie sesji działa poprzez przepisywanie"); out.println("URL-u, nawet wtedy gdy cookies nie są obsługiwane."); out.println("") ; } }
Aplet rozpoczyna tym samym kodem, który został zamieszczony w przykładzie 7.4, w aplecie SessionTracker. Następnie przechodzi do dalszego wyświetlania bieŜącego ID sesji, tego czy jest to sesja nowa, wartości limitu czasu, czasu utworzenia sesji oraz czas ostatniego połączenia z sesją. Później aplet wyświetla czy identyfikacja sesji (jeŜeli jest taka), będąca przedmiotem zlecenia, pochodzi od cookie czy od URL-u oraz czy to ID jest waŜne. W końcu aplet drukuje zakodowany URL, który moŜe zostać wykorzystany do powtórnego załadowania tej strony, w celu sprawdzenia czy przepisywanie URL-u działa nawet wtedy kiedy cookies nie są obsługiwane.
Zdarzenia wiąŜące sesję Niektóre obiekty mogą „chcieć” przeprowadzić operację zarówno wtedy, kiedy są związane z sesją, jak i wtedy kiedy nie są z nią związane. Dla przykładu, połączenie z bazą danych moŜe rozpoczynać transakcję (obsługę zlecenia) w stanie związania z sesją, a kończyć kiedy nie są z nią związane. Wszystkie obiekty, które wdraŜają interfejs javax.servlet.http.HttpSessionBindingListner, są powiadamiane o związaniu z sesją oraz o tym, Ŝe nie są z nią związane. Interfejs deklaruje dwie metody: valueBound() oraz valueUnbound(), które muszą zostać wdroŜone: public void HttpSessionBindingListener.valueBound( HttpSessionBindingEvent event) public void HttpSessionBindingListener.valueUnbound ( HttpSessionBindingEvent event)
Metoda valueBound() jest wywoływana, kiedy odbiornik jest związany z sesją, a metoda valueUnbound() kiedy odbiornik nie jest z nią związany — poprzez usunięcie, zastąpienie albo poprzez uniewaŜnienie sesji.
Argument javax.servlet.http.HttpSessionBindingEvent zapewnia dostęp do nazwy pod którą obiekt jest wiązany (lub odwiązywany od niej) z metodą getName(): public String HttpSessionBindingEvent.getName()
Rysunek 7.3. Przykładowy wydruk wyjściowy apletu „SessionSnoop”
Obiekt HttpSessionBindingEvent zapewnia równieŜ dostęp do obiektu, do którego jest wiązany (lub od którego jest „odwiązywany”) odbiornik, wykorzystując w tym celu metodę getSession(): public HttpSession HttpSessionBindingEvent.getSession()
Na
przykładzie 7.9 zaprezentowano uŜycie HttpSessionBindingListner oraz HttpSessionBindingEvent, z odbiornikiem rejestrującym w czasie związania jak i w czasie rozwiązania z sesją.
Przykład 7.9. Zdarzenia wiąŜące śledzenie sesji import import import import
java.io.*; java.util.*; javax.servlet.* ; javax.servlet.http.*;
public class SessionBindings extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IQException { res.setContentType("tekst/zwykły") ; PrintWriter out = res.getWriter(); // Pobierz aktualny obiekt sesji. w razie potrzeby utwórz go HttpSession session = reg.getSession(); // Dodaj CustomBindingListener session.setAttribute("bindings.listener", new CustomBindingListener(getServletContext())); out.println("Ta strona jest celowo pozostawiona pustą"); ) } class CustomBindingListener inplements HttpSessionBindingListener { // Zapisz ServletContext dla uŜytku jego metody log () ServletContext context; public CustomBindingListener(ServletContext context) { this.context = context; } public void valueBound(HttpSessionBindingEvent event) { context.log("[" + new Dated + "] BOUND as " + event.getName() + " to " + event. getSession () . getid ()) ; } public void valueUnbound(HttpSessionBindingEvent event) { context.log("[" + new Date() + "] UNBOUND as " + event.getName () + " from " + event. getSession().getId() ); } }
Za kaŜdym razem kiedy obiekt CustomBindingListner jest wiązany z sesją, jego metoda valueBound(), jest wywoływana i zdarzenie jest rejestrowane. Za kaŜdym razem kiedy obiekt ten jest „odwiązywany” od sesji, wywoływana jest jego metoda valueUnbound(), tak Ŝe zdarzenie jest równieŜ rejestrowane. MoŜemy śledzić sekwencję zdarzeń poprzez obserwowanie dziennika zdarzeń serwera.
ZałóŜmy, iŜ aplet ten jest wywołany jeden raz, powtórnie ładowany 30 sekund później i następnie nie wywoływany co najmniej przez następne pół godziny. Dziennik zdarzeń mógłby wyglądać w następujący sposób:
[Tue Sep 27 22:46:48 PST 2000] BOUND as bindings.listener to awj4qyhsn2 [Tue Sep 27 22:47:18 PST 2000] UNBOUND as bindings.listener from awj4qyhsn2 [Tue Sep 27 22:47:18 PST 2000] BOUND as bindings.listener to awj4qyhsn2 [Tue Sep 27 23:17:18 PST 2000] UNBOUND as bindings.listener from awj4qyhsn2
Pierwsza pozycja występuje podczas zlecenia pierwszej strony, kiedy odbiornik jest związany z nową sesją. Pozycje: druga oraz trzecia występują podczas ponownego ładowania, poniewaŜ odbiornik jest „odwiązywany” i powtórnie wiązany z sesją, w czasie tego samego wywołania setAttribute(). Czwarta pozycja ma miejsce pół godziny później, kiedy limit czasu sesji kończy się, a ona sama jest uniewaŜniana.
Robienie zakupów przy uŜyciu śledzenia sesji Zakończmy ten rozdział spojrzeniem na to, jak zadziwiająco prostym moŜe stać się nasz aplet „shopping cart viewer, przy zastosowaniu śledzenia sesji. Na przykładzie 7.10 zaprezentowano aplet zapisujący kaŜdy artykuł z koszyka, w sesji uŜytkownika, pod nazwą cart.items. Zwróćmy uwagę, iŜ URL-e, znajdujące się na stronie, zostały przepisane tak, aby obsługiwać klientów z zablokowanymi „Ciasteczkami”.
Przykład 7.10. Wykorzystanie Śledzenia Sesji API import java.io.*; import javax.servlet.* ; import javax.servlet.http.*; public class ShoppingCartViewerSession extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res. setContentType ("tekst/html") ; PrintWriter out = res.getWriter () ; // Pobierz obiekt bieŜącej sesji. HttpSession session = req.getSession(); // Artykuły z koszyka są utrzymywane w obiekcie sesji. String [] items = (String []) session. getAttribute ("cart. items") ; out.println("SessionTracker"); out.println("Session Tracking Demo");
// Drukuj aktualne artykuły z koszyka. out.println("Aktualnie masz w swoim koszyku następuje artykuły:
"); if (items == null) { out.println("None") ; } else ( out.println("
Aktualny czas to FRI OCT 25 23:17:37 GMT 2001
Domyślnie wszystkie dane wyświetlane przez ECS pojawiają się w jednej linii bez wcięć i powrotów karetki. Przyśpiesza to transfer podczas komunikacji z przeglądarką klienta. Aby otrzymać zawartość łatwiejszą do odczytania naleŜy dokonać edycji pliku ecs.properties, który jest dołączony do dystrybucji oraz zmienić wartość pretty_print na true. Następuje teraz trudniejsza część: naleŜy upewnić się, Ŝe plik ecs.properties zostanie odnaleziony w ścieŜce serwera przed plikiem JAR ECS, tak aby wyedytowany plik powodował pominięcie pliku ecs.properties zawartego w pliku JAR. Plik ecs.properties jest poszukiwany jako org/apache/ecs/ecs.properties, tak więc plik nie moŜe zostać umieszczony bezpośrednio w ścieŜce klas, ale w podkatalogu org/apache/ecs katalogu wewnątrz ścieŜki klas (na przykład WEBINF/classes/org/apache/ecs/ecs.properties). Serwlet importuje dwa pakiety ECS — org.apache.ecs zawierający podstawowe klasy ECS i org.apache.ecs.html zawierający klasy specyficzne dla HTML. (Istnieją inne pakiety odpowiedzialne za XML, WML i RTF.)1 Pakiet org.apache.ecs.html zawiera prawie sto klas reprezentujących wszystkie elementy HTML 4.0. Większość klas HTML nosi nazwy odpowiadające nazwom znaczników HTML — Big, Small, P, Table, TR, TD, TH, H1, H2, H3, Frame, A, Head, Body i tak dalej. KaŜda klasa HTML posiada metody słuŜące do konfiguracji elementu. Na przykład klasa TD posiada metodę setBackground(String url), która ustawia tło tej komórki tabeli. Klasa Body równieŜ posiada podobną metodę słuŜącą do ustawiania tła dla całej strony. śaden inny element ECS nie posiada metody setBackground(), poniewaŜ Ŝaden inny element nie posiada moŜliwości ustawienia swojego tła, co pozwala ECS na upewnienie się, Ŝe programowo utworzone elementy zawsze zawierają prawidłowo utworzony HTML.
1
Osoby zainteresowane programowym tworzeniem XML przy pomocy Javy powinny się raczej skupić na wykorzystaniu JDOM (http://jdom.org), poniewaŜ JDOM jest lepiej zintegrowany z technologiami XML.
Aby dodać elementy głównej części, serwlet wykorzystuje łączenie metod w łańcuchy, w których kilka metod jest wywoływanych na tym samym obiekcie. W ECS moŜna dotrzeć wiele takich konstrukcji. Na przykład, w celu utworzenia tabeli: Table tab = new Table() .setCellPadding(0) .setCellSpacing(0);
Puste miejsca nie mają znaczenia. PowyŜszy kod jest równy następującemu: Table tab = new Table().setCellPadding(0).setCellSpacing(0);
PowyŜszy łańcuch jest moŜliwy do utworzenia, poniewaŜ kaŜda metoda set i append zwraca odwołanie do obiektu, na którym została wywołana — odwołanie to jest wykorzystywane do wywołania następnej metody. Sztuczka ta często okazuje się przydatna przy korzystaniu z ECS.
Wyświetlanie zbioru wyników Wykorzystanie ECS do pełnego tworzenia strony wypadło z łask po ulepszeniu opartych na serwletach technologii szablonów. Po prostu dynamiczne tworzenie czegoś, co w większości jest statyczną zawartością strony zajmuje zbyt wiele czasu. Jednak ECS ciągle posiada swoje miejsce. ECS sprawdza się w przypadku tych części strony, które są wyjątkowo dynamiczne, w których do określenia zawartości do utworzenia konieczna jest pełna moc Javy. Jak powiedział Jon Stevens, jeden z jego twórców, „naleŜy wykorzystywać ECS wszędzie tam, gdzie w innym przypadku wystąpiłoby wyj.println().” Na przykład, proszę wyobrazić sobie aplikację WWW pozwalającą klientom na wykonywanie ad hoc zapytań w bazie danych. Na przykład mógł zostać zaimplementowany system śledzenia błędów i potrzebny jest serwlet dający zaawansowanym uŜytkownikom moŜliwość wykonywania swoich własnych zapytań w bazie danych (przy pomocy połączenia z uprawnieniami tylko-do-odczytu). ECS sprawdza się w tworzeniu strony wyświetlającej wyniki z baz danych, programowo tworząc tabelę dostosowaną do danych. Przykład 16.2 przedstawia prosty element przeglądający ResultSet. Przypomina on klasę HtmlSQLWynik przedstawioną w rozdziale 9, „Łączność z bazą danych”, która wykorzystywała wyj.println(). Zastosowanie ECS zamiast wyj.println() pozwala na uproszczenie i większe moŜliwości dostosowania kodu. Przykład 16.1. Ulepszona tabela ZbiorWynik import java.io.*; import java.sql.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*;
import org.apache.ecs.*; import org.apache.ecs.html.*;
public class ProstaTabelaResultSet extends Table {
public ProstaTabelaResultSet(ResultSet rs) throws SQLException { setBorder(1);
ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount();
TR rzad = new TR();
for (int i = 1; i JeŜeli ten napis jest widoczny, to utworzono nowy komponent!
JeŜeli nie jest konieczne umieszczenie głównej części, moŜe zostać wykorzystany skrót XML dla pustego znacznika />:
(Nowość!)
(Uaktualniony!)
Na początku wewnątrz skryptletu, jako łańcuchy String, definiowane są tytuły i opis strony. Następnie wykorzystana jest instrukcja include w celu dołączenia standardowej zawartości nagłówka z pliku naglowek.jsp oraz standardowej zawartości stopki (na końcu pliku) z pliku stopka.jsp. Instrukcja include umieszcza zawartość plików nagłówka i stopki do pliku podczas fazy tłumaczenia, tak więc zmienne tytul, tytul2 i opis są widoczne wewnątrz dołączanych plików, i plik naglowek.jsp wykorzystuje te zmienne. Pliki naglowek.jsp i stopka.jsp są przedstawione w przykładach 18.9 i 18.10. Przykład 18.9. Plik naglowek.jsp
Strona główna Hosting Mechanizmy |
| |||||
Strona główna Hosting Mechanizmy
|