3. Podstawy tworzenia stron internetowych w Javie
Przechodzimy teraz do tworzenia dynamicznych aplikacji internetowych, c.a.d. Są to aplikacje, w których strony HTML wysyłane do użytkownika są generowane przez programy.
3.1. Tworzenie projektu internetowego w Eclipse
Opracujemy pierwszą aplikację internetową przy użyciu Eclipse/Tomcat. Postępujemy analogicznie do procedury stosowanej przy tworzeniu aplikacji internetowej bez Eclipse. Po uruchomieniu Eclipse tworzymy nowy projekt:

który definiujemy jako dynamiczny projekt internetowy:

Na pierwszej stronie kreatora podajemy nazwę projektu [1] oraz jego lokalizację [2]:

Na drugiej stronie kreatora akceptujemy wartości domyślne:

Na ostatniej stronie kreatora pojawia się prośba o zdefiniowanie kontekstu aplikacji [3]:

Po zatwierdzeniu kreatora przez [Finish] program Eclipse łączy się ze stroną [http://java.sun.com] w celu pobrania niektórych dokumentów, które zamierza zapisać w pamięci podręcznej, aby uniknąć niepotrzebnych operacji sieciowych. Następnie pojawia się prośba o zatwierdzenie licencji:

Akceptujemy ją. Eclipse tworzy projekt internetowy. Aby go wyświetlić, wykorzystuje środowisko, zwane perspektywą, inne niż to używane w przypadku klasycznego projektu Java:

Perspektywą powiązaną z projektem internetowym jest perspektywa J2EE. Akceptujemy ją, aby zobaczyć... Uzyskany wynik jest następujący:

Perspektywa J2EE jest w rzeczywistości niepotrzebnie skomplikowana w przypadku prostych projektów internetowych. W tym przypadku wystarczy perspektywa Java. Aby ją uzyskać, używamy opcji [Window -> Open perspective -> Java]:

src: będzie zawierać kod Java klas aplikacji, a także pliki, które powinny znajdować się w katalogu Classpath aplikacji.
build/classes (nie pokazano): będzie zawierać pliki .class skompilowanych klas, a także kopię wszystkich plików innych niż .java umieszczonych w katalogu src. Aplikacja internetowa często korzysta z tak zwanych plików „zasobów”, które muszą znajdować się w katalogu Classpath aplikacji, czyli c.a.d. Zbiór wszystkich katalogów przeszukiwanych przez JVM, gdy aplikacja odwołuje się do klasy, czy to podczas kompilacji, czy podczas wykonywania. Eclipse dba o to, aby katalog build/classes stanowił część katalogu c web. Pliki „zasobów” umieszcza się w katalogu src, mając na uwadze, że Eclipse automatycznie skopiuje je do build/classes.
WebContent: będzie zawierać zasoby aplikacji internetowej, które nie muszą znajdować się w katalogu Classpath aplikacji.
WEB-INF/lib: będzie zawierać archiwa .jar potrzebne aplikacji internetowej.
Przyjrzyjmy się zawartości pliku [WEB-INF/web.xml], który konfiguruje aplikację [personne]:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name> personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Z tego typu konfiguracją mieliśmy już do czynienia podczas omawiania tworzenia stron startowych w punkcie 2.3.4. Plik ten służy wyłącznie do zdefiniowania zestawu stron startowych. Zachowujemy tylko pierwszą z nich. Plik [web.xml] przyjmuje następującą postać:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Zawartość powyższego pliku XML musi być zgodna z regułami składni określonymi w pliku wskazanym przez atrybut [xsi:schemaLocation] w tagu otwierającym <web-app>. W tym przypadku jest to plik [http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd]. Jest to plik XML, który można wyświetlić bezpośrednio w przeglądarce. Jeśli przeglądarka jest wystarczająco nowa, wyświetli plik XML:

Eclipse spróbuje zweryfikować poprawność dokumentu XML przy użyciu pliku .xsd określonego w atrybucie [xsi:schemaLocation] tagu otwierającego <web-app>. W tym celu nawiąże połączenie sieciowe. Jeśli komputer znajduje się w sieci prywatnej, należy wskazać programowi Eclipse serwer, za pomocą którego ma on opuścić sieć prywatną, zwany serwerem proxy HTTP. Odbywa się to za pomocą opcji [Window -> Preferences -> Internet]:

Zaznaczamy (1), jeśli znajdujemy się w sieci prywatnej. W polu (2) podajemy nazwę serwera obsługującego serwer proxy HTTP, a w polu (3) jego port nasłuchowy. Wreszcie w polu (4) należy wskazać komputery, dla których nie należy korzystać z serwera proxy – są to komputery znajdujące się w tej samej sieci prywatnej, co komputer, na którym pracujemy.
Teraz utworzymy plik [index.html] zawierający stronę główną.
3.2. Tworzenie strony głównej
Klikamy prawym przyciskiem myszy na folder [WebContent], a następnie wybieramy opcję [New -> Other]:

Wybieramy typ [HTML] i zamieniamy [Next] na ->

Powyżej wybieramy folder nadrzędny [WebContent] w punkcie (1) lub (2), a następnie w punkcie (3) podajemy nazwę pliku, który ma zostać utworzony. Po wykonaniu tych czynności przechodzimy do następnej strony kreatora:

Za pomocą opcji (1) możemy wygenerować plik HTML z danymi wstępnie wypełnionymi w polu (2). Jeśli odznaczamy opcję (1), generowany jest pusty plik HTML. Pozostawiamy zaznaczenie opcji (1), aby uzyskać szkielet kodu. Zakończamy pracę z kreatorem, wybierając opcję [Finish]. W ten sposób tworzony jest plik [index.html]:

o następującej treści:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
Modyfikujemy ten plik w następujący sposób:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Application personne</title>
</head>
<body>
Application personne active...
<br>
<br>
Vous êtes sur la page d'accueil
</body>
</html>
3.3. Test strony głównej
Jeśli nie jest widoczna, wyświetlimy widok [Servers] za pomocą opcji [Window - > Show View -> Other -> Servers], a następnie klikniemy prawym przyciskiem myszy na serwerze Tomcat 5.5:

Powyższa opcja [Add and Remove Objects] pozwala dodawać / usuwać aplikacje internetowe z serwera Tomcat:

Projekty internetowe rozpoznane przez Eclipse są wyświetlane w pozycji (1). Można je zarejestrować na serwerze Tomcat, korzystając z opcji (2). Aplikacje internetowe zarejestrowane na serwerze Tomcat pojawiają się w pozycji (4). Można je wyrejestrować, korzystając z opcji (3). Zarejestrujmy projekt [personne]:

a następnie zakończmy pracę kreatora rejestracji, wybierając [Finish]. Widok [Servers] pokazuje, że projekt [personne] został zarejestrowany na serwerze Tomcat:

Teraz uruchommy serwer Tomcat:
![]() | ![]() |
Uruchommy przeglądarkę internetową:

a następnie wpiszmy adres URL [http://localhost:8080/personne]. Jest to adres katalogu głównego aplikacji internetowej. Nie podano żadnego dokumentu. W takim przypadku wyświetlana jest strona główna aplikacji. Jeśli nie istnieje, pojawia się komunikat o błędzie. W tym przypadku strona główna istnieje. Jest to plik [index.html], który utworzyliśmy wcześniej. Uzyskany wynik wygląda następująco:

Jest to zgodne z oczekiwaniami. Teraz otwórzmy przeglądarkę zewnętrzną względem Eclipse i wpiszmy ten sam adres URL:

Aplikacja internetowa [personne] jest zatem rozpoznawalna również poza środowiskiem Eclipse.
3.4. Tworzenie formularza HTML
Teraz tworzymy statyczny dokument HTML o nazwie [formulaire.html] w folderze [personne]:

Aby go utworzyć, należy postępować zgodnie z procedurą opisaną w punkcie 3.2 na stronie 33. Jego zawartość będzie następująca:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Retablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Powyższy kod HTML odpowiada poniższemu formularzowi:

typ HTML | nazwa | kod HTML | rola | |
<input type="text"> | txtNom | wiersz 14 | wprowadzenie nazwy | |
<input type= "text "> | txtAge | wiersz 18 | wprowadzenie wieku | |
<input type="submit"> | wiersz 23 | wysyłanie wprowadzonych wartości na serwer pod adresem URL /personne1/main | ||
<input type="reset"> | wiersz 24 | w celu przywrócenia strony do stanu, w jakim została pierwotnie odebrana przez przeglądarkę | ||
<input type="button"> | wiersz 25 | w celu wyczyszczenia zawartości pól wprowadzania danych [1] i [2] |
Zapiszmy dokument w folderze <osoba>/WebContent. W razie potrzeby uruchommy Tomcat. W przeglądarce wywołajmy adres URL http://localhost:8080/personne/formulaire.html:

Architektura klient-serwer tej podstawowej aplikacji wygląda następująco:

Serwer WWW znajduje się pomiędzy użytkownikiem a aplikacją internetową i nie został tutaj przedstawiony. [formulaire.html] to dokument statyczny, który w odpowiedzi na każde żądanie klienta dostarcza tę samą treść. Programowanie internetowe ma na celu generowanie treści dostosowanej do żądania klienta. Treść ta jest wówczas generowana programowo. Pierwszym rozwiązaniem jest wykorzystanie strony JSP (Java Server Page) zamiast statycznego pliku HTML. Właśnie to teraz obejrzymy.
3.5. Tworzenie strony JSP
Odczyty [ref1]: rozdział 1, rozdział 2: 2.2, 2.2.1, 2.2.2, 2.2.3, 2.2.4
Poprzednia architektura klient-serwer zostaje przekształcona w następujący sposób:

Strona JSP jest odmianą strony HTML z ustawionymi parametrami. Niektóre elementy strony otrzymują swoje wartości dopiero w momencie wykonania. Wartości te są obliczane programowo. Mamy zatem do czynienia ze stroną dynamiczną: kolejne żądania dotyczące tej strony mogą skutkować różnymi odpowiedziami. Terminem „odpowiedź” określamy tutaj stronę HTML wyświetlaną przez przeglądarkę klienta. Ostatecznie przeglądarka zawsze otrzymuje dokument HTML. Ten dokument HTML jest generowany przez serwer WWW na podstawie strony JSP. Ta ostatnia służy jako szablon. Jej elementy dynamiczne są zastępowane rzeczywistymi wartościami w momencie generowania dokumentu HTML.
Aby utworzyć stronę JSP, klikamy prawym przyciskiem myszy na folder [WebContent], a następnie wybieramy opcję [New -> Other]:

Wybieramy typ [JSP] i wykonujemy [Next] ->

Powyżej wybieramy folder nadrzędny [WebContent] w punkcie (1) lub (2), a następnie w punkcie (3) podajemy nazwę pliku, który ma zostać utworzony. Po wykonaniu tych czynności przechodzimy do następnej strony kreatora:

Za pomocą opcji (1) możemy wygenerować plik JSP z danymi wstępnie wypełnionymi w polu (2). Jeśli odznaczamy opcję (1), generowany jest pusty plik JSP. Pozostawiamy zaznaczenie opcji (1), aby uzyskać szkielet kodu. Zakończamy pracę z kreatorem, wybierając opcję [Finish]. W ten sposób tworzony jest plik [formulaire.jsp]:

o następującej treści:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
Wiersz 1 wskazuje, że mamy do czynienia ze stroną JSP. Przekształcamy powyższy tekst w następujący sposób:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// pobieramy parametry
String nom=request.getParameter("txtNom");
if(nom==null) nom="inconnu";
String age=request.getParameter("txtAge");
if(age==null) age="xxx";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
Dokument, który początkowo był statyczny, stał się teraz dynamiczny dzięki wprowadzeniu kodu Java. W przypadku tego typu dokumentów zawsze postępujemy w następujący sposób:
- umieszczamy kod Java na samym początku dokumentu, aby pobrać parametry niezbędne do wyświetlenia dokumentu. Często znajdują się one w obiekcie request. Obiekt ten reprezentuje żądanie klienta. Żądanie to może przechodzić przez wiele serwletów i stron JSP, które mogły je wzbogacić. W tym przypadku dotrze do nas bezpośrednio z przeglądarki.
- Kod HTML znajduje się poniżej. Najczęściej ogranicza się on do wyświetlania zmiennych obliczonych wcześniej w kodzie Java za pomocą tagów <%= zmienna %>. Należy tutaj zwrócić uwagę, że znak = jest połączony ze znakiem %. Jest to częsta przyczyna błędów.
Czym zajmuje się powyższy dokument dynamiczny?
- wiersze 6–9: pobiera z zapytania dwa parametry o nazwach [txtNom] i [txtAge] i przypisuje ich wartości do zmiennych [nom] (wiersz 6) oraz [age] (wiersz 8). Jeśli nie znajdzie tych parametrów, przypisuje do powiązanych zmiennych wartości domyślne.
- Wyświetla wartość obu zmiennych [nom, age] w poniższym kodzie HTML (wiersze 25 i 29).
Przeprowadźmy pierwszy test. W razie potrzeby uruchommy Tomcat, a następnie w przeglądarce wywołajmy adres http://localhost:8080/personne/formulaire.jsp:

Dokument formulaire.jsp został wywołany bez przekazania parametrów. Wyświetlono zatem wartości domyślne. Teraz wywołajmy plik URL http://localhost:8080/personne/formulaire.jsp?txtNom=martin&txtAge=14:

Tym razem przekazaliśmy do dokumentu formulaire.jsp parametry txtNom i txtAge, których oczekiwał. W związku z tym wyświetlił je. Wiemy, że istnieją dwie metody przekazywania parametrów do dokumentu internetowego: GET i POST. W obu przypadkach przekazane parametry znajdują się w predefiniowanym obiekcie request. Tutaj zostały one przekazane za pomocą metody GET.
3.6. Tworzenie serwletu
Materiały do przeczytania [ref1]: rozdział 1, rozdział 2: 2.1, 2.1.1, 2.1.2, 2.3.1
W poprzedniej wersji żądanie klienta było przetwarzane przez stronę JSP. Podczas pierwszego wywołania tej strony serwer WWW, w tym przypadku Tomcat, tworzy klasę Java na podstawie tej strony i kompiluje ją. To właśnie wynik tej kompilacji ostatecznie przetwarza żądanie klienta. Klasa wygenerowana na podstawie strony JSP jest serwletem, ponieważ implementuje interfejs [javax.Servlet]:

Żądanie klienta może być przetworzone przez dowolną klasę implementującą ten interfejs. Teraz tworzymy taką klasę: ServletFormulaire. Poprzednia architektura klient/serwer ulega następującej transformacji:

W architekturze opartej na stronie JSP dokument HTML wysyłany do klienta był generowany przez serwer WWW na podstawie strony JSP, która służyła jako szablon. W tym przypadku dokument HTML wysyłany do klienta zostanie w całości wygenerowany przez serwlet.
3.6.1. Tworzenie serwletu
W programie Eclipse kliknijmy prawym przyciskiem myszy na folder [src] i wybierzmy opcję utworzenia klasy:

następnie zdefiniujmy właściwości tworzonej klasy:

W polu (1) wpisujemy nazwę pakietu, w polu (2) nazwę klasy, którą chcemy utworzyć. Klasa ta musi dziedziczyć po klasie wskazanej w polu (3). Nie ma potrzeby ręcznego wpisywania jej pełnej nazwy. Przycisk (4) umożliwia dostęp do klas znajdujących się obecnie w pakiecie Classpath aplikacji internetowej:

W polu (1) wpisuje się nazwę poszukiwanej klasy. W polu (2) wyświetlane są klasy z pliku Classpath, których nazwa zawiera ciąg znaków wpisany w polu (1).
Po zatwierdzeniu przez kreatora projekt internetowy [personne] został zmodyfikowany w następujący sposób:

Utworzono klasę [ServletFormulaire] wraz ze szkieletem kodu:

Powyższy zrzut ekranu pokazuje, że Eclipse sygnalizuje błąd [warning] w wierszu deklarującym klasę. Kliknijmy ikonę (żarówka) sygnalizującą ten błąd [warning]:

Po kliknięciu w (1) w (2) pojawiają się propozycje rozwiązań pozwalających usunąć błąd [warning]. Wybranie jednej z nich powoduje, że w (3) pojawia się zmiana kodu, do której doprowadzi ten wybór.
Wersja Java 1.5 wprowadziła zmiany w języku Java, w związku z czym to, co było poprawne w poprzedniej wersji, może teraz powodować błąd [warnings]. Błędy te nie sygnalizują błędów, które mogłyby uniemożliwić kompilację klasy. Ich celem jest zwrócenie uwagi programisty na fragmenty kodu, które można by ulepszyć. Wskazany komunikat [warning] oznacza, że klasa powinna posiadać numer wersji. Jest on wykorzystywany do serializacji/deserializacji obiektów, c.a.d. gdy obiekt Java .class znajdujący się w pamięci musi zostać przekształcony w ciąg bitów wysyłanych sekwencyjnie w strumieniu zapisu lub odwrotnie, gdy obiekt Java .class znajdujący się w pamięci musi zostać utworzony na podstawie ciągu bitów odczytywanych sekwencyjnie w strumieniu odczytu. Wszystko to jest dalekie od naszych obecnych problemów. Poprosimy więc kompilator o zignorowanie tego ostrzeżenia, wybierając rozwiązanie [Add @SuppressWarnings ...]. Kod przyjmuje wówczas następującą postać:

Nie ma już [warning]. Dodany wiersz nazywa się „adnotacją” – pojęciem, które pojawiło się wraz z wersją Java 1.5. Kod ten uzupełnimy w późniejszym terminie.
3.6.2. Ścieżka klasy projektu Eclipse
Classpath aplikacji Java to zbiór folderów i archives.jar przeszukiwanych podczas kompilacji przez kompilator lub podczas jej uruchamiania przez JVM. Te dwa Classpath niekoniecznie są identyczne, ponieważ niektóre klasy są potrzebne tylko podczas wykonywania, a nie podczas kompilacji. Zarówno kompilator Java, jak i JVM posiadają argument, który pozwala określić Classpath aplikacji przeznaczonej do kompilacji lub uruchomienia. W sposób mniej lub bardziej przejrzysty dla użytkownika Eclipse zapewnia utworzenie i przekazanie tego argumentu do JVM.
Jak można poznać elementy Classpath projektu Eclipse? Za pomocą opcji [<projet> / Build Path / Configure Build Path]:

Otrzymujemy wówczas następujący kreator konfiguracji:

Zakładka (1) [Libraries] pozwala zdefiniować listę plików .jar, które wchodzą w skład Classpath aplikacji. Są one zatem przeszukiwane przez JVM, gdy aplikacja żąda klasy. Przyciski [2] i [3] umożliwiają dodawanie archiwów do Classpath. Przycisk [2] pozwala wskazać archiwa znajdujące się w folderach projektów zarządzanych przez Eclipse, natomiast przycisk [3] pozwala wskazać dowolne archiwum z systemu plików komputera.
Powyżej widoczne są trzy biblioteki (Libraries):
- [JRE System Library]: biblioteka podstawowa dla projektów Java w Eclipse:

- [Tomcat v5.5 runtime]: biblioteka dostarczana przez serwer Tomcat. Zawiera klasy niezbędne do tworzenia aplikacji internetowych. Biblioteka ta jest dołączana do każdego projektu internetowego w Eclipse, który został powiązany z serwerem Tomcat.

To właśnie archiwum [servlet-api.jar] zawiera klasę [javax.servlet.http.HttpServlet], która jest klasą nadrzędną dla klasy [ServletFormulaire], którą właśnie tworzymy. To właśnie dlatego, że archiwum to znajduje się w archiwum Classpath aplikacji, mogło zostać zaproponowane jako klasa nadrzędna w kreatorze przedstawionym poniżej.

Gdyby tak nie było, nie pojawiłaby się ona wśród propozycji dla klasy [2]. Jeśli więc w tym kreatorze chcemy odwołać się do klasy nadrzędnej, a ta nie jest proponowana, oznacza to, że albo pomyliliśmy nazwę tej klasy, albo archiwum, które ją zawiera, nie znajduje się w pliku Classpath aplikacji.
- Plik [Web App Libraries] zawiera archiwa znajdujące się w folderze [WEB-INF/lib] projektu. Tutaj jest pusty:

Archiwa z katalogu Classpath projektu Eclipse są widoczne w eksploratorze projektów. Na przykład w przypadku projektu internetowego [personne]:

Eksplorator projektów zapewnia dostęp do zawartości tych archiwów:

Jak widać powyżej, to właśnie archiwum [servlet-api.jar] zawiera klasę [javax.servlet.http.HttpServlet].
3.6.3. Konfiguracja serwletu
Materiały do przeczytania [ref1]: rozdział 2: 2.3, 2.3.1, 2.3.2, 2.3.3, 2.3.4
Plik [WEB-INF/web.xml] służy do konfiguracji aplikacji internetowej:

Ten plik, dotyczący projektu [personne], ma obecnie następującą treść (patrz strona 32):
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Wskazuje on jedynie na istnienie pliku strony głównej (wiersz 8). Modyfikujemy go, aby zadeklarować:
- istnienie serwletu [ServletFormulaire]
- serwletów URL obsługiwanych przez ten serwlet
- parametry inicjalizacyjne serwletu
Plik web.xml naszej aplikacji „personne” będzie wyglądał następująco:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>formulairepersonne</servlet-name>
<url-pattern>/formulaire</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Główne elementy tego pliku konfiguracyjnego są następujące:
- wiersze 7–24 dotyczą obecności serwletu [ServletFormulaire]
- wiersze 7–20: konfiguracja serwletu odbywa się pomiędzy tagami <servlet> i </servlet>. Aplikacja może zawierać kilka serwletów, a zatem tyle samo sekcji konfiguracyjnych <servlet>...</servlet>.
- wiersz 8: tag <servlet-name> nadaje serwletowi nazwę – może to być dowolna nazwa
- wiersze 9–11: tag <servlet-class> podaje pełną nazwę klasy odpowiadającej serwletowi. Tomcat będzie szukał tej klasy w pliku Classpath projektu internetowego [personne]. Znajdzie ją w pliku [build/classes]:
![]()
- wiersze 12–15: tag <init-param> służy do przekazywania parametrów konfiguracyjnych do serwletu. Są one zazwyczaj odczytywane w metodzie init serwletu, ponieważ jego parametry konfiguracyjne muszą być znane już przy pierwszym załadowaniu.
- wiersze 13–14: tag <param-name> określa nazwę parametru, a <param-value> – jego wartość.
- wiersze 12–15 definiują parametr [defaultNom,"inconnu"], a wiersze 16–19 – parametr [defaultAge,"XXX"]
- wiersze 21–24: tag <servlet-mapping> służy do powiązania serwletu (servlet-name) z wzorcem URL (url-pattern). W tym przypadku wzorzec jest prosty. Oznacza on, że za każdym razem, gdy adres URL będzie miał postać /formularz, należy użyć serwletu formulairepersonne, c.a.d, klasy [istia.st.servlets.ServletFormulaire] (wiersze 8–11). Zatem serwlet [formulairepersonne] akceptuje tylko jeden adres URL.
3.6.4. Kod serwletu [ServletFormulaire]
Serwlet [ServletFormulaire] będzie miał następujący kod:
Już po pobieżnym zapoznaniu się z serwletem można zauważyć, że jest on znacznie bardziej złożony niż odpowiadająca mu strona JSP. Jest to ogólna zasada: serwlet nie nadaje się do generowania kodu HTML. Do tego celu służą strony typu JSP. Będziemy mieli okazję do tego wrócić. Wyjaśnijmy kilka ważnych kwestii dotyczących powyższego serwletu:
- gdy serwlet jest wywoływany po raz pierwszy, wywoływana jest jego metoda init (wiersz 20). Jest to jedyny przypadek, w którym jest ona wywoływana.
- jeśli serwlet został wywołany przez metodę HTTP GET, wywoływana jest metoda doGet (wiersz 32) w celu przetworzenia żądania klienta.
- jeśli serwlet został wywołany przez metodę HTTP POST, wywoływana jest metoda doPost (wiersz 82) w celu przetworzenia żądania klienta.
Metoda init służy tutaj do pobrania z pliku [web.xml] wartości parametrów inicjalizacyjnych o nazwach „defaultNom” i „defaultAge”. Metoda init, wykonywana podczas pierwszego załadowania serwletu, jest odpowiednim miejscem do pobrania zawartości pliku [web.xml].
- wiersz 22: pobierana jest konfiguracja projektu internetowego o nazwie „[config]”. Obiekt ten odzwierciedla zawartość pliku aplikacji o nazwie „[WEB-INF/web.xml]”.
- Wiersz 23: z tej konfiguracji pobierana jest wartość typu String parametru o nazwie „defaultNom”. Parametr ten będzie miał na wartości imię osoby. Jeśli nie istnieje, otrzymamy wartość null.
- wiersze 24–25: jeśli parametr o nazwie „defaultNom” nie istnieje, przypisujemy wartość domyślną do zmiennej [defaultNom].
- wiersze 26–29: podobnie postępujemy w przypadku parametru o nazwie „defaultAge”.
Metoda doPost odwołuje się do metody doGet. Oznacza to, że klient może wysyłać swoje parametry zarówno za pomocą metody POST, jak i GET.
Metoda doGet:
- wiersz 32: metoda otrzymuje dwa parametry: `request` i `response`. `request` to obiekt reprezentujący całe żądanie klienta. Jest to typ `HttpServletRequest`, który jest interfejsem. `response` jest typu `HttpServletResponse`, który również jest interfejsem. Obiekt `response` służy do wysłania odpowiedzi do klienta.
- request.getParameter("param") służy do pobrania z żądania klienta wartości parametru o nazwie „param”. W wierszu 36 pobierana jest wartość parametru „txtNom”, a w wierszu 40 – wartość parametru „txtAge”. Jeśli parametry te nie występują w żądaniu, jako wartość parametru uzyskuje się wartość null.
- wiersze 37–39: jeśli parametr „txtNom” nie występuje w zapytaniu, zmiennej „nom” przypisuje się domyślną nazwę „defaultNom”, zainicjowaną w metodzie init. To samo dotyczy wierszy 41–43 w odniesieniu do wieku.
- wiersz 45: response.setContentType(String) służy do ustalenia wartości nagłówka HTTP Content-type. Nagłówek ten informuje klienta o rodzaju dokumentu, który otrzyma. Typ text/html oznacza dokument HTML.
- wiersz 46: response.getWriter() służy do uzyskania strumienia zapisu do klienta
- wiersze 47–78: do strumienia zapisu uzyskanego w wierszu 46 zapisujemy dokument HTML, który ma zostać wysłany do klienta.
Kompilacja tego serwletu spowoduje utworzenie pliku .class w folderze [build/classes] projektu [personne]:

Zachęcamy czytelnika do zapoznania się z dokumentacją Java dotyczącą serwletów. Pomocne może być w tym przypadku wykorzystanie serwera Tomcat. Na stronie startowej Tomcat 5 znajduje się link [Documentation]:

Link ten prowadzi do strony, którą czytelnik może przeglądać. Link do dokumentacji serwletów jest następujący:

3.6.5. Test serwletu
Jesteśmy gotowi do przeprowadzenia testu. W razie potrzeby uruchommy serwer Tomcat.

Następnie w przeglądarce wywołajmy adresy URL oraz [http://localhost:8080/personne/formulaire]. W tym przypadku wywołujemy adres URL [/formulaire] z kontekstu [/personne]. Plik [web.xml] tego kontekstu wskazuje, że adres URL [/formulaire] jest obsługiwany przez serwlet o nazwie [formulairepersonne]. W tym samym pliku wskazano, że serwletem tym jest klasa o nazwie [istia.st.servlets.ServletFormulaire]. Tomcat powierzy zatem tej klasie przetwarzanie żądania klienta. Jeśli klasa nie została jeszcze załadowana, zostanie załadowana. Pozostanie ona wówczas w pamięci na potrzeby przyszłych żądań.
W przeglądarce wbudowanej w Eclipse otrzymujemy następujący wynik:

Otrzymujemy domyślne wartości imienia i wieku, zapisane w pliku [web.xml]. Teraz wywołajmy URL [http://localhost:8080/personne/formulaire?txtNom=tintin&txtAge=30]:

Tym razem otrzymujemy parametry przekazane w żądaniu. Jeśli czytelnik nie rozumie tych dwóch wyników, prosimy o ponowne zapoznanie się z kodem serwletu [ServletFormulaire].
3.6.6. Automatyczne odświeżanie kontekstu aplikacji internetowej
Uruchommy Tomcat:

a następnie zmodyfikujmy kod serwletu w następujący sposób:
- zmieniono wiersz 8
Zapiszmy nową klasę. Zapisanie spowoduje, że Eclipse automatycznie ponownie skompiluje klasę [ServletFormulaire], co zostanie wykryte przez Tomcat. Następnie Tomcat ponownie załaduje kontekst aplikacji internetowej [personne], aby uwzględnić zmiany. Informacja ta pojawia się w logach widoku [console]:

Wywołajmy adres URL [http://localhost:8080/personne/formulaire] bez ponownego uruchamiania serwera Tomcat:

Wprowadzona zmiana została poprawnie uwzględniona.
Teraz zmieńmy plik [web.xml] w następujący sposób:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<servlet>
<servlet-name>formulairepersonne</servlet-name>
...
<init-param>
<param-name>defaultNom</param-name>
<param-value>INCONNU</param-value>
</init-param>
...
</servlet>
...
</web-app>
- zmieniono wiersz 12
Po wykonaniu tej czynności zapiszmy nowy plik [web.xml]. W widoku [console] żaden wpis w dzienniku nie sygnalizuje ponownego załadowania kontekstu aplikacji. Wywołajmy adres URL [http://localhost:8080/personne/formulaire] bez ponownego uruchamiania serwera Tomcat:

Wprowadzona zmiana nie została uwzględniona. Uruchommy ponownie serwer Tomcat [clic droit sur serveur -> Restart -> Start]:

a następnie ponownie wywołajmy adres URL [http://localhost:8080/personne/formulaire]:

Tym razem zmiana wprowadzona w [web.xml] jest widoczna.
Zmiana w pliku [web.xml] nie powoduje zatem automatycznego przeładowania aplikacji, które uwzględniłoby nowy plik konfiguracyjny. Aby wymusić przeładowanie aplikacji internetowej, można ponownie uruchomić serwer Tomcat, tak jak to zrobiliśmy, ale jest to dość powolna operacja. Lepiej jest skorzystać z narzędzia [manager] do zarządzania aplikacjami wdrożonymi w Tomcacie. Aby było to możliwe, w środowisku Eclipse Tomcat musi być skonfigurowany zgodnie z instrukcją podaną w punkcie 2.5.
Najpierw, korzystając z wewnętrznej przeglądarki środowiska Eclipse, należy wpisać adres URL [http://localhost:8080], a następnie kliknąć link [Tomcat Manager], zgodnie z wyjaśnieniem na końcu punktu 2.5:

Otwórzmy drugą przeglądarkę [clic droit sur le navigateur -> New Editor]:
![]() | ![]() |
W tej drugiej przeglądarce wpiszmy adres URL [http://localhost:8080/formulaire]:

Zmodyfikujmy plik [web.xml] w następujący sposób, a następnie zapiszmy go:
<!-- ServletFormulaire -->
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>YYY</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
Następnie ponownie wywołajmy adres URL [http://localhost:8080/formulaire]. Możemy zauważyć, że zmiana nie została uwzględniona. Teraz przejdźmy do pierwszej przeglądarki i odświeżmy aplikację [personne]:

Następnie ponownie wywołajmy adres URL [http://localhost:8080/formulaire] w drugiej przeglądarce:

Zmiana w [web.xml] została uwzględniona. W praktyce warto mieć otwartą przeglądarkę z aplikacją [manager] w Tomcacie, aby radzić sobie z tego typu sytuacjami.
3.7. Współpraca serwletów i stron JSP
Materiały do lektury [ref1]: rozdział 2: 2.3.7
Wróćmy do dwóch analizowanych architektur:

Żadna z tych dwóch architektur nie jest zadowalająca. Obie mają tę wadę, że łączą dwie technologie: programowanie w języku Java, które odpowiada za logikę aplikacji internetowej, oraz kodowanie HTML, które odpowiada za prezentację informacji w przeglądarce.
- Rozwiązanie [1] oparte na stronie JSP ma tę wadę, że łączy kod HTML i kod Java w obrębie tej samej strony. Nie zauważyliśmy tego w omawianym przykładzie, który był prosty. Gdyby jednak [formulaire.jsp] musiało sprawdzić poprawność parametrów [txtNom, txtAge] w żądaniu klienta, bylibyśmy zmuszeni umieścić kod Java na stronie. Szybko staje się to niemożliwe do opanowania.
- Rozwiązanie oparte na serwlecie [2] ma ten sam problem. Chociaż w klasie znajduje się wyłącznie kod Java, musi ona generować dokument HTML. Również w tym przypadku, o ile dokument HTML nie jest prosty, jego generowanie staje się skomplikowane i praktycznie niemożliwe do utrzymania.
Aby uniknąć mieszania technologii Java i HTML, zastosujemy następującą architekturę:

- użytkownik wysyła swoje żądanie do serwletu. Serwlet przetwarza je i tworzy wartości dynamicznych parametrów strony JSP [formulaire.jsp], które posłużą do wygenerowania odpowiedzi HTML dla klienta. Wartości te tworzą tzw. szablon strony JSP.
- Po zakończeniu pracy serwlet zwróci się do strony JSP i [formulaire.jsp] o wygenerowanie odpowiedzi HTML dla klienta. Jednocześnie przekaże mu elementy, których strona JSP potrzebuje do wygenerowania tej odpowiedzi – elementy te tworzą model strony.
Przyjrzyjmy się teraz tej nowej architekturze.
3.7.1. Serwlet [ServletFormulaire2]
W powyższej architekturze serwlet będzie nosił nazwę [ServletFormulaire2]. Zostanie on utworzony w tym samym projekcie [personne], co poprzednio, podobnie jak wszystkie przyszłe serwlety:

[ServletFormulaire2] uzyskuje się najpierw poprzez skopiowanie i wklejenie [ServletFormulaire] w środowisku Eclipse:
- zaznacz [ServletFormulaire.java] -> kliknij prawym przyciskiem myszy -> Kopiuj
- zaznacz [istia.st.servlets.personne] -> kliknij prawym przyciskiem myszy -> Wklej -> zmień nazwę na [ServletFormulaire2.java]
Następnie modyfikujemy kod pliku [ServletFormulaire2] w następujący sposób:
Zmieniła się jedynie część odpowiedzialna za generowanie odpowiedzi HTTP (wiersze 44–46):
- wiersz 46: generowanie odpowiedzi zostało powierzone stronie JSP formulaire2.jsp. Strona ta, której jeszcze nie omówiono, będzie odpowiedzialna za wyświetlenie parametrów pobranych z żądania klienta: imienia (wiersze 35–38) i wieku (wiersze 39–42).
- Te dwie wartości są umieszczane w atrybutach zapytania [request], powiązanych z kluczami. Atrybuty zapytania są zarządzane jako słownik.
- wiersz 44: imię jest umieszczane w zapytaniu powiązanym z kluczem „imię”
- wiersz 45: wiek jest umieszczany w zapytaniu powiązanym z kluczem „wiek”
- wiersz 46: żąda wyświetlenia strony JSP [formulaire2.jsp]. Jako parametr przekazuje się do niej:
- żądanie klienta o nazwie [request], co umożliwi stronie JSP dostęp do jej atrybutów, które zostały właśnie zainicjowane przez serwlet
- odpowiedź [response], co pozwoli stronie JSP wygenerować odpowiedź HTTP dla klienta
Po napisaniu klasy [ServletFormulaire2] jej skompilowany kod pojawia się w pliku [build/classes]:

3.7.2. Strona JSP [formulaire2.jsp]
Stronę JSP formulaire2.jsp uzyskuje się poprzez skopiowanie i wklejenie strony [formulaire.jsp]

a następnie przekształcono w następujący sposób:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// pobieramy wartości niezbędne do wyświetlenia
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Personne - formulaire2</title>
</head>
<body>
<center>
<h2>Personne - formulaire2</h2>
<hr>
<form action="" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
</tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
W porównaniu z [formulaire.jsp] zmieniły się jedynie wiersze 4–8:
- wiersz 6: pobiera wartość atrybutu o nazwie „nom” z zapytania [request], atrybutu utworzonego przez serwlet [ServletFormulaire2].
- wiersz 7: wykonuje tę samą operację dla atrybutu „age”
3.7.3. Konfiguracja aplikacji
Plik konfiguracyjny [web.xml] zostaje zmodyfikowany w następujący sposób:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>personne</display-name>
<!-- ServletFormulaire -->
<servlet>
<servlet-name>formulairepersonne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXXX</param-value>
</init-param>
</servlet>
<!-- ServletFormulaire 2-->
<servlet>
<servlet-name>formulairepersonne2</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletFormulaire2
</servlet-class>
<init-param>
<param-name>defaultNom</param-name>
<param-value>inconnu</param-value>
</init-param>
<init-param>
<param-name>defaultAge</param-name>
<param-value>XXX</param-value>
</init-param>
</servlet>
<!-- Mapowanie ServletFormulaire -->
<servlet-mapping>
<servlet-name>formulairepersonne</servlet-name>
<url-pattern>/formulaire</url-pattern>
</servlet-mapping>
<!-- Mapowanie ServletFormulaire 2-->
<servlet-mapping>
<servlet-name>formulairepersonne2</servlet-name>
<url-pattern>/formulaire2</url-pattern>
</servlet-mapping>
<!-- pliki startowe -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Zachowaliśmy dotychczasową zawartość i dodaliśmy:
- wiersze 22–36: sekcję <servlet> w celu zdefiniowania nowego serwletu ServletFormulaire2
- wiersze 42–46: sekcję <servlet-mapping> w celu powiązania z nią URL /formularz2
W razie potrzeby uruchom lub ponownie uruchom serwer Tomcat. Wymagamy serwletu URL
http://localhost:8080/personne/formulaire2?txtNom=milou&txtAge=10:

Otrzymujemy ten sam wynik co poprzednio, ale struktura naszej aplikacji jest teraz bardziej przejrzysta: serwlet zawierający logikę aplikacji i przekazujący stronie JSP zadanie wysłania odpowiedzi do klienta. Od tej pory będziemy zawsze postępować w ten sposób.



