Skip to content

12. Aplikacja internetowa MVC [personne] – wersja 7

12.1. Introduction

W tej wersji zakładamy, że mogą istnieć przeglądarki klienckie, które zablokowały:

  1. wysyłanie plików cookie wysyłanych przez serwer
  2. wykonywanie kodu JavaScript osadzonego w wyświetlanych stronach HTML

Chcemy jednak, aby tego typu przeglądarki mogły korzystać z naszej aplikacji. Punkt 2 odsyła nas do wersji 2 naszej aplikacji, ponieważ JavaScript został wprowadzony dopiero od wersji 3. Wersja 2 działała bez JavaScriptu, więc punkt 2 jest rozwiązany.

Punkt 1 może, ale nie musi być trudny do rozwiązania. Wersja 6 naszej aplikacji działała bez plików cookie. Łącząc wersje 2 i 6, uzyskujemy pożądany rezultat. Dodamy jeszcze jedno ograniczenie: aplikacja musi obsługiwać sesję. Nie jest to ograniczenie bez sensu. W aplikacji, w której użytkownicy muszą się uwierzytelnić, serwer musi zapamiętać parę (identyfikator / hasło) użytkownika, aby uniknąć konieczności uwierzytelniania się przy każdym wywołaniu strony.

Do tej pory wykorzystaliśmy trzy rozwiązania do przechowywania informacji w trakcie wymiany danych między klientem a serwerem:

  1. sesja
  2. pliki cookie
  3. ukryte pola.

Rozwiązanie nr 2 można wykluczyć, ponieważ przeglądarka klienta może zablokować korzystanie z plików cookie.

Rozwiązanie nr 3 to rozwiązanie z wersji 6, które omówiliśmy wcześniej. Nie można go jednak zastosować ze względów bezpieczeństwa. Jeśli para (login/hasło) jest zawarta w każdej stronie wysyłanej do przeglądarki, oznacza to, że jest ona przesyłana przez sieć przy każdej wymianie danych między klientem a serwerem. Nie jest to korzystne dla bezpieczeństwa aplikacji. Można zatem rozważyć zastosowanie protokołu HTTPS, który szyfruje komunikację między klientem a serwerem. Jednak stosowanie go dla każdej strony aplikacji zwiększy obciążenie serwera.

Można by chcieć wykluczyć rozwiązanie 1, ponieważ również opiera się ono na plikach cookie. Podczas pierwszej wymiany danych między klientem a serwerem serwer wysyła do klienta token sesji, który ten będzie odsyłał do serwera przy każdym nowym żądaniu. Dzięki temu tokenowi serwer będzie mógł rozpoznać swojego klienta i przypisać mu informacje, które zapamiętał podczas poprzedniej wymiany. Token sesji jest wysyłany przez serwer w pliku cookie. Przeglądarka, która nie zablokowała plików cookie, może odesłać ten plik cookie podczas kolejnych żądań. Jeśli zablokowała pliki cookie, ma inne rozwiązanie: może dołączyć token sesji do adresu URL, o który prosi. Właśnie to widzimy teraz, wracając do analizy pliku [index.jsp] z wersji 4:


<%@ 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="/main"/>

Przypominamy, że wiersz 5 powyżej przekierowuje klienta do adresu URL [/personne4/main?jsessionid=XX], gdzie XX jest tokenem sesji, jak pokazuje poniższy zrzut ekranu uzyskany po wysłaniu żądania do adresu URL [http://localhost:8080/personne4]:

Image

Przyjrzyjmy się bliżej działaniu tagu <c:redirect> w odniesieniu do tokenu sesji. Weźmy przeglądarkę, w której akceptowane są pliki cookie. Poniżej konfigurujemy przeglądarkę Firefox:

Image

W [1] zezwalamy na pliki cookie, a w [2] usuwamy te, które już istnieją, aby zacząć od znanej sytuacji. Następnie wysyłamy żądanie do adresu URL [http://localhost:8080/personne4]. Otrzymujemy następującą odpowiedź:

Image

Pierwotne żądanie klienta HTTP brzmiało następująco:

1
2
3
4
5
6
7
8
9
GET /personne4/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

Warto zauważyć, że klient nie wysyła pliku cookie sesji. Odpowiedź HTTP wysłana przez serwer wygląda następująco:

1
2
3
4
5
6
7
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC; Path=/personne4
Location: http://localhost:8080/personne4/main;jsessionid=1ACA010A6BA28FB9E30A1D3184F574BC
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Tue, 23 May 2006 09:10:05 GMT
  • wiersz 1: serwer prosi klienta o przekierowanie
  • wiersz 3: serwer wysyła token sesji powiązany z atrybutem [JSESSIONID]
  • wiersz 4: adres URL przekierowania zawiera token sesji. Został on umieszczony tam przez tag <c:redirect>, ponieważ klient nie wysłał pliku cookie sesji.

Przeglądarka, do której skierowano żądanie przekierowania, wysłała następnie następujące żądanie:

GET /personne4/main;jsessionid=1ACA010A6BA28FB9E30A1D3184F574BC HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC
  • wiersz 1: przeglądarka żąda adresu URL przekierowania wraz z tokenem sesji. Dlatego właśnie na zrzucie ekranu przeglądarka wyświetla ten adres URL.
  • wiersz 10: przeglądarka odsyła token sesji, który otrzymała od serwera podczas poprzedniej wymiany danych. Tak właśnie działają pliki cookie, gdy są one dozwolone w przeglądarce klienta. Jeśli tak nie jest, otrzymane pliki cookie nie są odsyłane.

Serwer odpowiedział na to drugie żądanie następującą treścią:

1
2
3
4
5
HTTP/1.x 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 2376
Date: Tue, 23 May 2006 09:10:05 GMT

Serwer znalazł żądaną stronę i ją wysyła. Należy zauważyć, że nie wysyła już tokenu sesji. Tak właśnie działa token sesji: serwer wysyła go do przeglądarki tylko raz w postaci pliku cookie, a przeglądarka następnie odsyła go przy każdym żądaniu, aby zostać rozpoznaną.

Teraz, korzystając z tej samej przeglądarki, ponownie wywołajmy adres URL [http://localhost:8080/personne4], wpisując go ręcznie. Otrzymujemy wówczas następującą stronę:

Image

Zauważamy, że adres URL wyświetlany przez przeglądarkę nie zawiera już tokenu sesji. Przyjrzyjmy się pierwszej wymianie danych między klientem a serwerem:

Przeglądarka wysłała następujące żądanie:

GET /personne4 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC

Jest to dokładnie to samo żądanie, co poprzednio, z jedną jednak różnicą: w wierszu 10 przeglądarka odsyła token sesji, który otrzymała podczas pierwszej wymiany danych. Ponownie jest to normalne zachowanie, jeśli pliki cookie w przeglądarce są aktywne.

Serwer wysłał następującą odpowiedź:

1
2
3
4
5
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Location: http://localhost:8080/osoba4/
Transfer-Encoding: chunked
Date: Tue, 23 May 2006 09:24:39 GMT

Wzywa klienta do przekierowania. Ponieważ otrzymał token sesji od klienta, kontynuuje tę sesję i nie wysyła nowego tokenu sesji. Z tego samego powodu tag <c:redirect> nie uwzględnia tego tokenu sesji w adresie URL przekierowania. Dlatego adres URL widoczny na powyższym zrzucie ekranu nie zawiera tokenu sesji.

Z tego wszystkiego wynika następująca zasada: tag <c:redirect> dołącza token sesji do adresu URL przekierowania tylko wtedy, gdy klient nie wysłał nagłówka HTTP:

Cookie: JSESSIONID=1ACA010A6BA28FB9E30A1D3184F574BC

Zasada ta dotyczy również tagu <c:url>, z którym zapoznamy się w dalszej części.

Co się dzieje w przeglądarce, w której wyłączono pliki cookie? Sprawdźmy to. Najpierw zresetujemy przeglądarkę:

Image

W [1] wyłączamy pliki cookie, a w [2] usuwamy te, które już istnieją, aby zacząć od znanej sytuacji. Następnie wysyłamy żądanie do adresu URL [http://localhost:8080/personne4]. Otrzymujemy następującą odpowiedź:

Image

Otrzymujemy ten sam wynik co poprzednio. Wymiany danych HTTP nie są jednak dokładnie takie same:

GET /personne4/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0,5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=911B8156E0A9D32C2D256020C898E05C; Path=/personne4
Location: http://localhost:8080/osoba4/main;jsessionid=911B8156E0A9D32C2D256020C898E05C
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Tue, 23 May 2006 09:39:55 GMT

GET /personne4/main;jsessionid=911B8156E0A9D32C2D256020C898E05C HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: fr-fr,fr;q=0.8,en;q=0.6,en-us;q=0.4,de;q=0.2
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

HTTP/1.x 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 2376
Date: Tue, 23 May 2006 09:39:55 GMT
  • wiersze 1–9: żądanie nr 1 z przeglądarki. Nie wysyła ona pliku cookie sesji.
  • wiersze 11–17: odpowiedź serwera z prośbą o przekierowanie na inny adres URL. Serwer wysyła plik cookie sesji w wierszu 13: tag <c:redirect> dołączył token do adresu URL przekierowania w wierszu 14.
  • wiersze 19–27: żądanie nr 2 przeglądarki. Nie odsyła ona pliku cookie sesji, który właśnie otrzymała od serwera, ponieważ ma wyłączoną obsługę plików cookie.
  • wiersze 29–33: odpowiedź serwera. Można zauważyć, że mimo iż przeglądarka nie przesłała mu pliku cookie sesji, serwer nie rozpoczyna jednak nowej sesji, jak można by się spodziewać. Widać to po tym, że nie wysyła nagłówka HTTP [Set-Cookie], tak jak to zrobił w wierszu 13. Oznacza to, że kontynuuje poprzednią sesję. Udało mu się ją odnaleźć dzięki tokenowi sesji zawartemu w adresie URL żądanym przez przeglądarkę w wierszu 19.

Należy zauważyć, że serwer śledzi sesję, pobierając token sesji wysłany przez klienta na dwa możliwe sposoby:

  • w nagłówku HTTP [Set-Cookie] wysłanym przez klienta
  • w adresie URL żądanego przez klienta

Teraz, korzystając z tej samej przeglądarki, ponownie wywołajmy adres URL [http://localhost:8080/personne4], wpisując go ręcznie, tak jak to miało miejsce, gdy pliki cookie były dozwolone. Otrzymujemy wówczas następującą stronę:

Image

Wynik różni się od tego uzyskanego, gdy pliki cookie były dozwolone: token sesji znajduje się w adresie URL wyświetlanym przez przeglądarkę. Wyjaśnijmy ten wynik bez analizowania wymiany danych HTTP, która miała miejsce:

[cookies autorisés]

  • podczas drugiego żądania adresu URL [http://localhost:8080/personne4] przeglądarka klienta odesłała plik cookie sesji, który otrzymała od serwera podczas pierwszego żądania tego samego adresu URL. Tag <c:redirect> nie uwzględnił zatem tokenu sesji w adresie przekierowania.

[cookies inhibés]

  • podczas drugiego żądania adresu URL [http://localhost:8080/personne4] przeglądarka klienta nie wysyła pliku cookie sesji, który otrzymała od serwera podczas pierwszego żądania tego samego adresu URL, ponieważ jej pliki cookie są wyłączone. Tag <c:redirect> uwzględnia zatem token sesji w adresie przekierowania. Dlatego właśnie widoczny jest on na powyższym zrzucie ekranu.

Tagi <c:redirect> i <c:url> umożliwiają dołączenie tokenu sesji do adresów URL. Jest to rozwiązanie proponowane w niniejszym artykule.

12.2. Projekt Eclipse

Aby utworzyć projekt Eclipse [mvc-personne-07] dla aplikacji internetowej [/personne7], należy skopiować projekt [mvc-personne-06], postępując zgodnie z procedurą opisaną w punkcie 6.2.

12.3. Konfiguracja aplikacji internetowej [personne7]

Plik web.xml aplikacji /personne7 ma następującą treść:


<?xml version="1.0" encoding="UTF-8"?>
...
    <display-name>mvc-personne-07</display-name>
...

Plik ten jest identyczny z plikiem z poprzedniej wersji, z wyjątkiem wiersza 3, w którym nazwa wyświetlana aplikacji internetowej została zmieniona na [mvc-personne-07]. Strona główna [index.jsp] pozostaje bez zmian.


...
<c:redirect url="/do/formulaire"/>

12.4. Kod widoków

Widoki [formulaire, réponse, erreurs] powracają do stanu z wersji 2, c.a.d, bez JavaScriptu. Zachowują jednak tagi JSTL z ostatnich wersji.

12.4.1. Widok [formulaire]

Image

Usunięto przyciski powiązane z kodem JavaScript.

[formulaire.jsp]:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>

<html>
  <head>
    <title>Personne - formulaire</title>
  </head>
  <body>
    <center>
      <h2>Personne - formulaire</h2>
      <hr>
      <form name="frmPersonne" action="<c:url value="validationFormulaire"/>" 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>
          <tr>
        </table>
        <table>
          <tr>
            <td><input type="submit" name="bouton" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="submit" name="bouton" value="Effacer"></td>
          </tr>
        </table>
      </form>
    </center>
  </body>
</html>
  • wiersz 14: docelowy adres URL dla POST jest zapisany za pomocą tagu <c:url>, aby token sesji znalazł się w nim na wypadek, gdyby klientem była przeglądarka, która nie wysyła nagłówka HTTP [Cookie].
  • Formularz zawiera dwa przyciski typu [submit]: [Envoyer] (wiersz 28) oraz [Effacer] (wiersz 30). Oba przyciski mają tę samą nazwę: bouton. Po kliknięciu przycisku POST przeglądarka wyśle parametr:
  • przycisk=Wyślij, jeśli żądanie POST zostało wywołane przez przycisk [Wyślij]
  • przycisk=Usuń, jeśli żądanie POST zostało wywołane przez przycisk [Usuń]

To właśnie ten parametr pomoże nam określić dokładną akcję, którą należy wykonać, ponieważ adres URL [/do/validationFormulaire] odpowiada teraz dwóm odrębnym akcjom.

12.4.2. Widok [réponse]

Image

[réponse.jsp]:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td>${nom}</td>
      </tr>
        <tr>
          <td>Age</td>
        <td>${age}</td>
      </tr>
    </table>      
    <br>
    <a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
  </body>
</html>

  • wiersz 24: docelowy adres URL widoku HREF jest zapisany za pomocą tagu <c:url>, aby token sesji znalazł się w nim na wypadek, gdyby klientem była przeglądarka, która nie wysyła nagłówka HTTP [Cookie].

12.4.3. Widok [erreurs]

Image

[erreurs.jsp]:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
            <c:forEach var="erreur" items="${erreurs}">
                <li>${erreur}</li>
            </c:forEach>
    </ul>
    <br>
    <a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
  </body>
</html>

  • wiersz 18: docelowy adres URL widoku HREF jest zapisany za pomocą tagu <c:url>, aby token sesji znalazł się w nim na wypadek, gdyby klientem była przeglądarka, która nie wysyła nagłówka HTTP [Cookie].

Zachęcamy czytelnika do przetestowania tych nowych widoków zgodnie z zasadą omówioną w poprzednich wersjach.

12.5. Kontroler [ServletPersonne]

Kontroler [ServletPersonne] aplikacji internetowej [/personne7] wygląda następująco:

package istia.st.servlets.personne;

...

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
     // parametry instancji
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse","lienRetourFormulaire"};
    private Map params=new HashMap<String,String>();

     // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
...
    }

     // GET
    @SuppressWarnings("unchecked")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

...
         // pobieramy metodę wysyłania żądania
        String méthode=request.getMethod().toLowerCase();
         // pobieramy akcję do wykonania
        String action=request.getPathInfo();
...
        if(méthode.equals("post") && action.equals("/validationFormulaire")){
             // walidacja formularza wprowadzania danych
            doValidationFormulaire(request,response);
            return;
        }
        if(méthode.equals("get") && action.equals("/retourFormulaire")){
             // powrót do formularza wprowadzania danych
            doRetourFormulaire(request,response);
            return;
        }
         // inne przypadki
        doInit(request,response);
    }

     // wyświetlenie pustego formularza
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

     // wyświetlenie wstępnie wypełnionego formularza
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // wyświetlanie formularza
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

     // wyświetlanie pustego formularza
    void doEffacer(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // przygotowuje się szablon formularza
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
         // wyświetlanie formularza
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

     // walidacja formularza
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // pobieranie przycisku, który wywołał POST
        String bouton = request.getParameter("bouton").toLowerCase();
         // przetwarzanie w zależności od przycisku, który wywołał POST
        if(bouton==null){
            doInit(request,response);
            return;
        }
        if("envoyer".equals(bouton)){
            doEnvoyer(request,response);
            return;
        }
        if("effacer".equals(bouton)){
            doEffacer(request,response);
            return;
        }
    }

     // walidacja formularza
    void doEnvoyer(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // pobieramy parametry
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
         // i zapisujemy je w sesji
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", nom);
        session.setAttribute("age", age);
         // link powrotny do formularza jest umieszczany w szablonie widoków [réponse, erreurs]
        request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));    
         // sprawdzanie parametrów
        ArrayList<String> erreursAppel = new ArrayList<String>();
    ...
         // czy występują błędy w parametrach?
        if (erreursAppel.size() != 0) {
             // wysyłamy stronę z komunikatem o błędzie
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            return;
        }
         // parametry są poprawne – wysyłamy stronę odpowiedzi
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }

     // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
...
    }
}
  • wiersz 35: akcja [/retourFormulaire] jest wykonywana przez GET, a nie już przez POST, jak w poprzedniej wersji.
  • wiersze 70–87: akcja [/validationFormulaire] jest wykonywana przez akcję POST, wywołaną kliknięciemjednego z przycisków [Envoyer] lub [Effacer] w widoku [formulaire]. Metoda [doValidationFormulaire] obsługuje te dwa przypadki za pomocą dwóch różnych metod.
  • wiersze 90–103: metoda [doEnvoyer] odpowiada metodzie [doValidationFormulaire] z poprzedniej wersji. Wprowadzone dane są umieszczane w sesji (wiersze 96–98), podczas gdy w poprzedniej wersji były umieszczane w zapytaniu.
  • wiersze 58–67: nowa metoda [doEffacer] powinna wyświetlać pusty formularz. Można by skorzystać z metody [doInit], która już wykonuje tę czynność. W tym miejscu korzystamy również z okazji, aby usunąć elementy [nom, age] z sesji, tak aby nadal odzwierciedlała ona aktualny stan formularza.
  • wiersze 50–55: powodują wyświetlenie widoku [formulaire] bez widocznej inicjalizacji szablonu tego widoku. Szablon ten składa się w rzeczywistości z elementów [nom, age], które już znajdują się w sesji. Nie ma potrzeby wykonywania żadnych dodatkowych czynności.

12.6. Tests

Uruchom lub ponownie uruchom Tomcat po dodaniu do niego projektu Eclipse [personne-mvc-07], a następnie wywołaj adres URL [http://localhost:8080/personne7] w przeglądarce, w której wyłączono obsługę plików cookie i usunięto już istniejące. Otrzymujemy następującą odpowiedź:

Image

Kod źródłowy otrzymany przez przeglądarkę jest następujący:

1
2
3
<form name="frmPersonne" action="validationFormulaire;jsessionid=9D4CC83FEFB51AE78B1FD71EC66F9EF3" method="post">
...
</form>

W wierszu 1 token sesji znajduje się w docelowym adresie URL POST.

Wypełnijmy formularz i prześlijmy go:

Image

Kod źródłowy otrzymany przez przeglądarkę wygląda następująco:

1
2
3
4
...
    <br>
    <a href="retourFormulaire;jsessionid=9D4CC83FEFB51AE78B1FD71EC66F9EF3">Retour au formulaire</a>
  </body>

Wiersz 3: token sesji znajduje się w docelowym adresie URL linku.