10. Aplikacja internetowa MVC [personne] – wersja 5
10.1. Introduction
W tej wersji wprowadzamy dwie zmiany:
Pierwsza dotyczy sposobu, w jaki klient informuje serwer o akcji, którą chce wykonać. Do tej pory była ona określana za pomocą parametru o nazwie [action] w żądaniu wysyłanym przez klienta o nazwie GET lub POST. W tym przypadku akcja będzie określona przez ostatni element adresu URL żądanego przez klienta, jak pokazuje poniższa sekwencja:

W przypadku [1] adres URL, na który wysłano formularz, to [/personne5/do/validationFormulaire]. To właśnie ostatni element adresu URL, [validationFormulaire], pozwolił kontrolerowi rozpoznać akcję, którą należy wykonać. W przypadku [2], akcja POST wywołana przez link [Retour au formulaire] została wykonana pod adresem URL [/personne5/do/retourFormulaire]. Również w tym przypadku ostatni element adresu URL, [retourFormulaire], wskazuje kontrolerowi, jaką akcję należy wykonać.
Wprowadzamy tę zmianę, ponieważ jest to metoda stosowana przez najpopularniejsze frameworki do tworzenia stron internetowych, takie jak Struts czy Spring MVC.
Wszystkie adresy URL aplikacji będą miały postać [/personne5/do/action]. Plik [web.xml] aplikacji [/personne5] wskaże, że aplikacja ta akceptuje adresy URL w postaci [/do/*]:
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
Kontroler pobierze nazwę akcji do wykonania w następujący sposób:
Metoda [getPathInfo] obiektu [request] zwraca ostatni element adresu URL żądania.
Druga wprowadzona zmiana dotyczy sposobu przechowywania danych wprowadzonych przez użytkownika pomiędzy dwoma cyklami żądania/odpowiedzi. Obecnie informacje te są przechowywane w sesji. Metoda ta może mieć swoje wady, jeśli jest wielu użytkowników i trzeba zapamiętać duże ilości danych dla każdego z nich. Każdy użytkownik ma bowiem swoją osobistą sesję. Ponadto sesja ta pozostaje aktywna przez pewien czas po opuszczeniu serwisu przez użytkownika, chyba że zapewniono mu opcję wylogowania. W ten sposób 1000 sesji po 1000 bajtów zajmie 1 MB pamięci. Jest to nadal umiarkowane zapotrzebowanie i niewiele jest aplikacji, w których jednocześnie aktywnych jest 1000 sesji.
Istnieją jednak alternatywy dla sesji, mniej obciążające pamięć, i warto je znać. W tym przypadku wykorzystamy metodę plików cookie. Zilustrujmy to na przykładzie.
Krok 1: użytkownik zatwierdza formularz:
![]() |
Ten cykl żądania/odpowiedzi powoduje następującą wymianę danych HTTP między klientem a serwerem:
[1] : [demande du client]
Jest to typowy przypadek POST. Nie ma tu nic szczególnego do odnotowania, poza tym, że mimo iż nie będziemy korzystać z sesji, serwer WWW i tak ją tworzy. Widać to po tokenie sesji, który przeglądarka odsyła do serwera w wierszu 11 i który wcześniej otrzymała od serwera.
[2]: [réponse du serveur]
Widać, że w wierszach 3 i 4 do przeglądarki klienta wysłano nagłówki HTTP i [Set-Cookie] – jeden dotyczący imienia (wiersz 3), a drugi wieku (wiersz 4). Wartości tych plików cookie to wartości przesłane w wierszu 14 powyższych nagłówków POST i [1].
Krok 2: Powrót do formularza

Ten cykl żądania/odpowiedzi powoduje następującą wymianę danych HTTP między klientem a serwerem:
[1] : [demande du client]
Obserwujemy tutaj komunikat POST wywołany kliknięciem linku [Retour au formulaire]. W wierszu 11 widzimy, że przeglądarka odsyła do serwera pliki cookie, które otrzymała ([nom, age, JSESSIONID]), za pomocą nagłówka HTTP [Cookie]. Na tej zasadzie działają pliki cookie. Klient odsyła do serwera pliki cookie, które otrzymał od niego. W tym przykładzie kontroler otrzyma wartości [pauline, 18], które musi umieścić w polach [txtNom, txtAge] widoku [formulaire] wyświetlanego w [2].
[2] : [réponse du serveur]
Nie ma tu nic szczególnego do odnotowania poza tym, że w tej odpowiedzi serwer nie wysłał żadnych plików cookie. Nie przeszkodzi to jednak przeglądarce w odesłaniu podczas następnej wymiany wszystkich plików cookie, które otrzymała od serwera, nawet jeśli nie ma to żadnego sensu. Zmniejsza się zatem obciążenie dostępnej pamięci serwera kosztem zwiększenia przepływu znaków w wymianie danych między klientem a serwerem.
10.2. Projekt Eclipse
Aby utworzyć projekt Eclipse [mvc-personne-05] dla aplikacji internetowej [/personne5], należy skopiować projekt [mvc-personne-04], postępując zgodnie z procedurą opisaną w punkcie 6.2.
![]() | ![]() |
10.3. Konfiguracja aplikacji internetowej [personne5]
Plik web.xml aplikacji /personne5 ma następującą treść:
<?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>mvc-personne-05</display-name>
<!-- ServletPersonne -->
<servlet>
<servlet-name>personne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletPersonne
</servlet-class>
...
</servlet>
<!-- Mapowanie ServletPersonne-->
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
<!-- pliki startowe -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Plik ten jest identyczny z plikiem z poprzedniej wersji, z wyjątkiem kilku szczegółów:
- wiersz 6: nazwa wyświetlana aplikacji internetowej zmieniła się na [mvc-personne-05]
- wiersz 18: adresy URL przetwarzane przez aplikację mają postać [/do/*]. Wcześniej przetwarzany był tylko adres URL [/main]. Teraz mamy tyle adresów URL, ile jest akcji do przetworzenia.
Strona główna [index.jsp] ulega zmianie:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/do/formulaire"/>
- wiersz 5: strona [index.jsp] przekierowuje klienta na adres URL [/personne5/do/formulaire], co sprowadza się do polecenia kontrolerowi wykonania akcji [formulaire].
10.4. Kod widoków
Widoki [formulaire, réponse, erreurs] ulegają niewielkim zmianom. Jedyna zmiana polega na tym, że akcja do wykonania nie jest już określana w taki sam sposób jak wcześniej, kiedy to była definiowana w ukrytym polu o nazwie [action] w wysyłanych formularzach. Obecnie jest ona określona w docelowym adresie URL wysyłanych formularzy, c.a.d, w atrybucie [action] tagu <form>:
[formulaire.jsp]:
...
<html>
<head>
<title>Personne - formulaire</title>
<script language="javascript">
...
</script>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="validationFormulaire" method="post">
...
</form>
</center>
</body>
</html>
- wiersz [13]: parametr [action] formularza pojawia się ponownie po pewnym czasie nieobecności w poprzednich wersjach. Aby zrozumieć wartość tego atrybutu w tym miejscu, należy pamiętać, że wszystkie adresy URL przetwarzane przez aplikację mają postać [/do/action]. W wierszu [13] atrybut [action] ma wartość adresu URL względnego (niezaczynającego się od /). W związku z tym przeglądarka uzupełni go adresem URL aktualnie wyświetlanej strony, a więc koniecznie adresem URL o postaci [/do/action]. Ostatni element zostanie zastąpiony względnym adresem URL z atrybutu [action] w tagu <form>, co da adres URL [/do/validationFormulaire] jako cel dla POST.
- Ukryte pole [action] zniknęło
[réponse.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- wiersz [7]: docelowym elementem dla POST będzie [/do/retourFormulaire]
- ukryte pole [action] zniknęło z formularza w wierszach 7–8.
[erreurs.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- wiersz [6]: docelowym polem dla POST będzie [/do/retourFormulaire]
- ukryte pole [action] zniknęło z formularza w wierszach 6–7.
Zachęcamy czytelnika do przetestowania tych nowych widoków zgodnie z zasadą omówioną w poprzednich wersjach.
10.5. Kontroler [ServletPersonne]
Kontroler [ServletPersonne] aplikacji internetowej [/personne5] będzie obsługiwał następujące akcje:
nr | żądanie | źródło | przetwarzanie |
1 | [GET /personne5/do/formulaire] | adres URL wpisany przez użytkownika | - wysłać pusty widok [formulaire] |
2 | [POST /osoba5/do/validationFormulaire] z parametrami [txtNom, txtAge] opublikowanych | kliknięcie przycisku [Envoyer] w widoku [formulaire] | - sprawdzić wartości parametrów [txtNom, txtAge] - jeśli są nieprawidłowe, wyślij widok [erreurs(erreurs)] - jeśli są prawidłowe, wyślij widok [reponse(nom,age)] |
3 | [POST /osoba5/do/retourFormulaire] bez wysyłania parametrów | kliknij link [Powrót do formularza] w widokach [réponse] i [erreurs]. | - wysłanie widoku [formulaire] wstępnie wypełnionego najnowszymi wprowadzonymi wartościami |
Szkielet kontrolera [ServletPersonne] jest identyczny jak w poprzedniej wersji. Omówimy zmiany wprowadzone w metodach [doValidationFormulaire, doRetourFormulaire, doGet], ponieważ metody [init, doInit, doPost] pozostały bez zmian.
10.5.1. Metoda [doGet]
Metoda [doGet] nie pobiera akcji do wykonania w taki sam sposób jak w poprzednich wersjach:
- wiersz 12: pobierana jest akcja do wykonania. Ma ona postać [/action].
- wiersze 18–22: przetwarzanie akcji [/formulaire] wywołanej przez żądanie GET
- wiersze 23–27: przetwarzanie akcji [/validationFormulaire], o którą poproszono w żądaniu POST
- wiersze 28–32: przetwarzanie akcji [/retourFormulaire] wywołanej przez żądanie POST
10.5.2. Metoda [doValidationFormulaire]
Metoda ta przetwarza żądanie nr 2 [POST /personne5/do/validationFormulaire] wraz z [txtNom, txtAge] w przesłanych elementach. Jej kod jest następujący:
Nowości:
- metoda [doValidationFormulaire] zwraca w odpowiedzi jeden z widoków [réponse, erreurs]. Niezależnie od treści tej odpowiedzi kontroler umieszcza w niej dwa pliki cookie (wiersze 8–9). Plik cookie jest reprezentowany przez obiekt [Cookie], którego konstruktor przyjmuje dwa parametry: klucz pliku cookie oraz wartość z nim powiązaną.
- wiersz 8: wartość wprowadzona w polu „nazwa” jest umieszczana w pliku cookie o kluczu „nazwa”
- wiersz 9: wartość wprowadzona dla pola „wiek” jest umieszczana w pliku cookie o kluczu „wiek”
- Plik cookie jest dodawany do odpowiedzi HTTP wysyłanej do klienta za pomocą metody [response.addCookie]. Odpowiedź ta jest tutaj jedynie przygotowywana. Zostanie ona faktycznie wysłana dopiero po wykonaniu strony JSP z widoku przesłanego do klienta.
10.5.3. Metoda [doRetourFormulaire]
Metoda ta przetwarza żądanie nr 2 [POST /personne5/do/retourFormulaire] bez przesłanych elementów. Jej kod jest następujący:
Nowości:
Metoda [doRetourFormulaire] ma wyświetlać formularz wstępnie wypełniony ostatnimi wprowadzonymi danymi. W poprzedniej wersji dane te były przechowywane w sesji. W obecnej wersji nie korzysta się już z sesji, lecz z plików cookie do zapamiętywania elementów między kolejnymi wymianami danych między klientem a serwerem. Gdy klient zażądał zatwierdzenia formularza, otrzymał w odpowiedzi widok [réponse] lub [erreurs], w zależności od sytuacji, wraz z dwoma plikami cookie o nazwach „nom” i „age”. Po kliknięciu linku [Retour au formulaire] w tych dwóch widokach, co powoduje wyświetlenie widoku POST pod adresem URL [/do/retourFormulaire], przeglądarka odeśle do serwera dwa otrzymane pliki cookie.
- wiersze 4–18: pobieramy wartości plików cookie o nazwach „nazwa” i „wiek”. Co dość dziwne, nie istnieje metoda pozwalająca uzyskać wartość pliku cookie na podstawie jego klucza. W związku z tym musimy przejrzeć każdy z otrzymanych plików cookie.
- Po wykonaniu tej czynności dwie uzyskane wartości są umieszczane w szablonie widoku [formulaire] (wiersze 20–21), aby mógł je wyświetlić.
10.6. Tests
Uruchom lub ponownie uruchom Tomcat po dodaniu do niego projektu Eclipse [personne-mvc-05], a następnie wywołaj adres URL [http://localhost:8080/personne5].


