Skip to content

6. Aplikacja internetowa MVC [personne] – wersja 2

Teraz zaproponujemy warianty poprzedniej aplikacji [/personne1], które nazwiemy [/personne2, /personne3, ...]. Warianty te nie zmieniają pierwotnej architektury aplikacji, która pozostaje następująca:

Image

W przypadku tych wariantów nasze wyjaśnienia będą krótsze. Przedstawimy jedynie zmiany wprowadzone w stosunku do poprzedniej wersji.

6.1. Introduction

Teraz zamierzamy dodać do naszej aplikacji obsługę sesji. Przypomnijmy sobie następujące kwestie:

  • dialog klient-serwer HTTP to ciąg niepowiązanych ze sobą sekwencji żądanie-odpowiedź
  • sesja służy jako pamięć między różnymi sekwencjami żądania-odpowiedzi tego samego użytkownika. Jeśli jest N użytkowników, to istnieje N sesji.

Poniższa sekwencja ekranów przedstawia, jak powinna teraz działać aplikacja:


Wymiana nr 1


demande
réponse

Nowością jest link powrotny do formularza, który został dodany w widoku [erreurs].


Wymiana nr 2


demande
réponse

W wymianie nr 1 użytkownik podał dla pary (nazwisko, wiek) wartości (xx, yy). Jeśli w trakcie wymiany serwer poznał te wartości, to pod koniec wymiany je „zapomina”. Można jednak zauważyć, że podczas wymiany nr 2 serwer jest w stanie ponownie wyświetlić te wartości w swojej odpowiedzi. To właśnie pojęcie sesji pozwala w tym przypadku serwerowi internetowemu zapamiętywać dane w trakcie kolejnych wymian danych między klientem a serwerem. Istnieją również inne możliwe rozwiązania tego problemu.

W trakcie wymiany nr 1 serwer zapamiętuje w sesji parę (imię, wiek), którą przesłał mu klient, aby móc ją wyświetlić podczas wymiany nr 2.

Oto kolejny przykład wykorzystania sesji między dwiema wymianami:


Wymiana nr 1


demande
réponse

Nowością jest link powrotny do formularza, który został dodany na stronie z odpowiedzią.


Wymiana nr 2


demande
réponse

6.2. Projekt Eclipse

Aby utworzyć projekt Eclipse [mvc-personne-02] dla aplikacji internetowej [/personne2], skopiujemy projekt Eclipse [mvc-personne-01], aby wykorzystać istniejące zasoby. W tym celu postępujemy w następujący sposób:

[clic droit sur projet mvc-personne-01 -> Copy]:

Image

a następnie [clic droit dans Package Explorer -> Paste]:

– w polu [1] wpisz nazwę nowego projektu, a w polu [2] nazwę istniejącego, ale pustego folderu

W ten sposób tworzony jest projekt o nazwie [mvc-personne-02]:

Image

Na razie jest on identyczny z projektem [mvc-personne-01]. Zanim będziemy mogli z niego korzystać, konieczne będzie wprowadzenie kilku zmian ręcznie. Przejdźmy do widoku [Servers] i spróbujmy dodać tę nową aplikację do tych zarządzanych przez Tomcat:

Widać, że w przypadku projektu [1] nowy projekt [mvc-personne-02] nie jest wykrywany przez Tomcat. Aby Tomcat go wykrył, należy zmodyfikować plik konfiguracyjny projektu [mvc-personne-02]. Użyjmy opcji [File / Open File], aby otworzyć plik [<mvc-personne-02>/.settings/.component]:


<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId">
<wb-module deploy-name="mvc-personne-01">
<wb-resource deploy-path="/" source-path="/WebContent"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
<property name="java-output-path" value="/build/classes/"/>
<property name="context-root" value="personne1"/>
</wb-module>
</project-modules>

Wiersz 3 określa nazwę modułu internetowego, który ma zostać wdrożony w Tomcat. Nazwa ta jest tutaj taka sama jak nazwa projektu [mvc-personne-01]. Zmieniamy ją na [mvc-personne-02]:


<wb-module deploy-name="mvc-personne-02">

Ponadto możemy przy okazji zmienić w wierszu 7 nazwę kontekstu aplikacji [mvc-personne-02], która koliduje z nazwą projektu [mvc-personne-01]:


<property name="context-root" value="personne2"/>

Tę drugą zmianę można było wprowadzić bezpośrednio w Eclipse. Nie znalazłem jednak sposobu, aby dokonać pierwszej zmiany bez korzystania z pliku konfiguracyjnego.

Po wykonaniu tych czynności zapisujemy nowy plik [.content], a następnie zamykamy i ponownie uruchamiamy Eclipse, aby zmiany zostały uwzględnione.

Po ponownym uruchomieniu Eclipse spróbujmy wykonać operację, która wcześniej zakończyła się niepowodzeniem:

Tym razem projekt [mvc-personne-02] jest prawidłowo rozpoznawany. Dodajemy go do projektów skonfigurowanych do uruchamiania przez Tomcat:

Image

6.3. Konfiguracja aplikacji internetowej [personne2]

Plik web.xml aplikacji /personne2 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-02</display-name>
    <!--  ServletPersonne -->
    <servlet>
        <servlet-name>personne</servlet-name>
        <servlet-class>
            istia.st.servlets.personne.ServletPersonne
        </servlet-class>
        <init-param>
            <param-name>urlReponse</param-name>
            <param-value>
                /WEB-INF/vues/reponse.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlErreurs</param-name>
            <param-value>
                /WEB-INF/vues/erreurs.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlFormulaire</param-name>
            <param-value>
                /WEB-INF/vues/formulaire.jsp
            </param-value>
        </init-param>
        <init-param>
            <param-name>urlControleur</param-name>
            <param-value>
                main
            </param-value>
        </init-param>
        <init-param>
            <param-name>lienRetourFormulaire</param-name>
            <param-value>
                Retour au formulaire
            </param-value>
        </init-param>
    </servlet>
    <!--  Mapowanie ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  pliki powitalne -->
    <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 tego, że zawiera dwa nowe parametry inicjalizacyjne:

  • wiersz 6: nazwa wyświetlana aplikacji internetowej została zmieniona na [mvc-personne-02]
  • wiersze 31–36: definiują parametr konfiguracyjny o nazwie [urlControleur], który jest adresem URL [main] prowadzącym do serwletu [ServletPersonne]
  • wiersze 37–42: definiują parametr konfiguracyjny o nazwie [lienRetourFormulaire], który jest tekstem linku powrotnego do formularza na stronach JSP, [erreurs.jsp] i [reponse.jsp].

Strona główna [index.jsp] ulega zmianie:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
  response.sendRedirect("/personne2/main");
%>
  • wiersz 5: strona [index.jsp] przekierowuje klienta do adresu URL kontrolera [ServletPersonne] aplikacji [/personne2].

6.4. Kod widoków

6.4.1. Widok [formulaire]

Ten widok jest identyczny jak w poprzedniej wersji:

Image

Jest on generowany przez następujące strony: JSP i [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">
<%
    // pobieranie danych z szablonu
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>
    
<html>
    <head>
      <title>Personne - formulaire</title>
  </head>
  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <form action="<%=urlAction%>" 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" value="Envoyer"></td>
            <td><input type="reset" value="Rétablir"></td>
            <td><input type="button" value="Effacer"></td>
          </tr>
        </table>
        <input type="hidden" name="action" value="validationFormulaire"> 
      </form>
    </center>
  </body>
</html>

Nowości:

  • w wierszu 19 formularz posiada teraz atrybut [action], którego wartością jest adres URL, pod który przeglądarka ma wysłać wartości formularza, gdy użytkownik kliknie przycisk [Envoyer] typu submit. Zmienna [urlAction] przyjmie wartość action="main". Widok [formulaire] jest wyświetlany po wykonaniu przez użytkownika następujących czynności:
  • pierwsze żądanie: GET /osoba2/główna
  • kliknięcie linku [Retour au formulaire]: GET /osoba2/main?action=retourFormulaire

Ponieważ atrybut [action] nie określa adresu URL bezwzględnego (zaczynającego się od /), lecz względnego (niezaczynającego się od /), przeglądarka wykorzysta pierwszą część adresu URL aktualnie wyświetlanej strony [/personne2] i doda do niej adres względny. Adres URL dla POST będzie zatem brzmiał [/personne2/main], czyli adres kontrolera. Do tego żądania POST dołączone zostaną parametry [txtNom, txtAge, action] z wierszy 23, 27 i 38.

  • wiersz 8: pobierana jest wartość elementu [urlAction] z modelu. Jest ona wyszukiwana w atrybutach bieżącego żądania. Zostanie ona wykorzystana w wierszu 19.
  • wiersze 6–7: pobierane są wartości elementów [nom, age] z modelu. Są one wyszukiwane w atrybutach sesji, a nie w atrybutach zapytania, jak miało to miejsce w poprzedniej wersji. Ma to na celu zaspokojenie potrzeb zapytania [GET /personne2/main?action=retourFormulaire] związanego z widokami [réponse] i [erreurs]. Przed wyświetleniem tych dwóch widoków kontroler umieszcza w sesji dane wprowadzone w formularzu, co pozwala mu je odzyskać, gdy użytkownik korzysta z linku [Retour au formulaire] widoków [réponse] i [erreurs].

6.4.2. Widok [reponse]

Ten widok wyświetla wartości wprowadzone w formularzu, o ile są one prawidłowe:

W porównaniu z poprzednią wersją nowością jest link [Retour au formulaire]. Widok jest generowany przez następującą stronę: JSP [reponse.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">


<%
    // pobieranie danych z modelu
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Personne - réponse</h2>
    <hr>
    <table>
        <tr>
          <td>Nom</td>
        <td><%= nom %>
      </tr>
        <tr>
          <td>Age</td>
        <td><%= age %>
      </tr>
    </table>      
    <br>
    <a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
  </body>
</html>
  • wiersz 31: link powrotny do formularza. Link ten składa się z dwóch części:
    • cel [href="?action=retourFormulaire"]. Widok [réponse] jest wyświetlany po widoku POST formularza [formulaire.jsp] pod adresem URL [/personne2/main]. To właśnie ten ostatni adres URL jest wyświetlany w przeglądarce, gdy wyświetlany jest widok [réponse]. Kliknięcie linku [Retour au formulaire] spowoduje wówczas wysłanie żądania GET przez przeglądarkę do adresu URL określonego przez atrybut [href] linku, w tym przypadku „?action=retourFormulaire”. W przypadku braku adresu URL w [href] przeglądarka użyje adresu aktualnie wyświetlanego widoku, c.a.d. [/personne2/main]. Ostatecznie kliknięcie linku [Retour au formulaire] spowoduje wysłanie żądania GET przez przeglądarkę do adresu URL [/personne2/main?action=retourFormulaire], c.a.d – adres URL kontrolera aplikacji wraz z parametrem [action], który wskazuje mu, co ma wykonać.
    • Tekst linku. Będzie on częścią szablonu przekazanego stronie przez kontroler i pobranego w linii 10.

6.4.3. Widok [erreurs]

Ten widok sygnalizuje błędy wprowadzenia danych w formularzu:

W porównaniu z poprzednią wersją nowością jest link [Retour au formulaire]. Widok jest generowany przez następującą stronę: JSP [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">
<%@ page import="java.util.ArrayList" %>

<%
// pobieranie danych z modelu
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

<html>
    <head>
      <title>Personne</title>
  </head>
  <body>
      <h2>Les erreurs suivantes se sont produites</h2>
    <ul>
        <%
          for(int i=0;i<erreurs.size();i++){
            out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
        }//dla
      %>
    </ul>
    <br>
    <a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
  </body>
</html>

  • wiersz 26: link powrotny do formularza. Link ten jest identyczny z linkiem w widoku [réponse]. Zachęcamy czytelnika do ponownego zapoznania się z objaśnieniami dotyczącymi tego widoku.

6.5. Testowanie widoków

Aby przeprowadzić testy powyższych widoków, duplikujemy ich strony JSP w folderze /WebContent/JSP projektu Eclipse:

Image

Następnie w folderze JSP strony są modyfikowane w następujący sposób:

[formulaire.jsp]:


...
<%
  // -- test: tworzy się szablon strony
  session.setAttribute("nom","tintin");
  session.setAttribute("age","30");
  request.setAttribute("urlAction","main");
%>

<%
    // pobieramy dane z szablonu
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>

Dodano wiersze 4–5 w celu utworzenia szablonu wymaganego przez stronę w wierszach 11–13.

[reponse.jsp]:



<%
  // -- test: tworzymy szablon strony
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
  request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>

<%
    // pobieramy dane z szablonu
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>


Wiersze 4–6 zostały dodane w celu utworzenia szablonu wymaganego przez stronę w wierszach 11–13.

[erreurs.jsp]:



<%
  // -- test: tworzymy szablon strony
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
  request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>

<%
// pobieranie danych z szablonu
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>


Wiersze 4–8 zostały dodane w celu utworzenia szablonu wymaganego przez stronę w wierszach 13–14.

Uruchommy Tomcat, jeśli jeszcze tego nie zrobiliśmy, a następnie wywołajmy następujące adresy URL:

 

Otrzymujemy oczekiwane widoki.

6.6. Kontroler [ServletPersonne]

Kontroler [ServletPersonne] aplikacji internetowej [/personne2] będzie obsługiwał następujące akcje:

nr
żądanie
źródło
przetwarzanie
1
[GET /personne2/main]
adres URL wpisany przez użytkownika
- wyślij pusty widok [formulaire]
2
[POST /personne2/main]
z parametrami [txtNom,
txtAge, akcja] przesłane
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
[GET /osoba2/main?
action=powrótDoFormularza]
kliknij link [Powrót do
formularz] w widokach
odpowiedzi] i [erreurs].
- wysłanie widoku [formulaire] wstępnie wypełnionego najnowszymi wprowadzonymi wartościami

Mamy zatem nową akcję do przetworzenia: [GET /personne2/main?action=retourFormulaire].

6.6.1. Szkielet kontrolera

Szkielet kontrolera [ServletPersonne] jest niemal identyczny jak w poprzedniej wersji:

package istia.st.servlets.personne;

...
import javax.servlet.http.HttpSession;

@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    ...

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

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

     // 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{
        ...
    }

     // walidacja formularza
    void doValidationFormulaire(HttpServletRequest request,
    ...
    }

     // wysyłanie
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    ...
    }
}

Nowości:

  • wiersz 4: korzystanie z sesji wymaga zaimportowania pakietu [HttpSession]
  • wiersze 28–30: nowa metoda [doRetourFormulaire] obsługuje nową akcję: [GET /personne2/main?action=retourFormulaire].

6.6.2. Inicjalizacja kontrolera [init]

Metoda [init] jest identyczna jak w poprzedniej wersji. Sprawdza ona obecność w pliku [web.xml] elementów zadeklarowanych w tablicy [paramètres]:

1
2
3
4
5
6
public class ServletPersonne extends HttpServlet {
     // parametry instancji
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse","urlControleur","lienRetourFormulaire"};
  private Map params=new HashMap<String,String>();
  • wiersz 5: dodano parametry [urlControleur] (adres URL kontrolera) oraz [lienRetourFormulaire] (tekst linku w widokach [réponse] i [erreurs]).

6.6.3. Metoda [doGet]

Metoda [doGet] musi obsłużyć akcję [GET /personne2/main?action=retourFormulaire], która wcześniej nie istniała:

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

         // sprawdzanie przebiegu inicjalizacji serwletu
        if (erreursInitialisation.size() != 0) {
             // przekazujemy kontrolę do strony błędów
            request.setAttribute("erreurs", erreursInitialisation);
            request.setAttribute("lienRetourFormulaire", "");
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
             // koniec
            return;
        }
         // pobieramy metodę wysyłania żądania
        String méthode=request.getMethod().toLowerCase();
         // pobieramy akcję do wykonania
        String action=request.getParameter("action");
         // akcja?
        if(action==null){
            action="init";
        }
         // wykonanie akcji
        if(méthode.equals("get") && action.equals("init")){
             // uruchomienie aplikacji
            doInit(request,response);
            return;
        }
        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);
    }
  • wiersze 6–14: sprawdzamy, czy lista błędów inicjalizacji jest pusta. Jeśli tak nie jest, wyświetlamy widok [erreurs(erreursInitialisation)], który zgłosi błąd lub błędy.

Aby zrozumieć ten kod, należy przypomnieć sobie szablon widoku [erreurs]:


<%
// pobieranie danych z szablonu
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

Widok [erreurs] oczekuje w zapytaniu elementu klucza „erreurs”. Kontroler tworzy ten element w linii 8. Oczekuje on również elementu klucza „lienRetourFormulaire”. Kontroler tworzy ten element w linii 9. W tym przypadku tekst linku będzie pusty. W wysyłanym widoku [erreurs] nie będzie zatem żadnego linku. Jeśli bowiem wystąpiły błędy podczas inicjalizacji aplikacji, należy ją ponownie skonfigurować. Nie ma potrzeby proponowania użytkownikowi kontynuowania działania aplikacji za pomocą linku.

  • wiersze 34–37: obsługa nowej akcji [GET /personne2/main?action=retourFormulaire]

6.6.4. Metoda [doInit]

Metoda ta przetwarza żądanie nr 1 [GET /personne2/main]. W odpowiedzi na to żądanie musi wysłać pusty widok [formulaire(nom,age)]. Jej kod wygląda następująco:

     // wyświetlenie pustego formularza
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // pobieranie sesji użytkownika
        HttpSession session = request.getSession(true);        
         // wysyłanie pustego formularza
        session.setAttribute("nom", "");
        session.setAttribute("age", "");
        request.setAttribute("urlAction", (String)params.get("urlControleur"));
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
  • wiersz 4: pobierana jest bieżąca sesja, jeśli istnieje, w przeciwnym razie jest tworzona (parametr true z getSession).
  • wiersze 9–10: wyświetlany jest widok [formulaire]. Przypomnijmy model oczekiwany przez ten widok:

<%
    // pobieranie danych z modelu
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>
  • wiersze 6–7: elementy [nom,age] z modelu widoku [formulaire] są inicjowane pustymi ciągami znaków i umieszczane w sesji, ponieważ właśnie tam oczekuje ich widok.
  • wiersz 8: element [urlAction] modelu jest inicjowany wartością parametru [urlControleur] z pliku [web.xml] i umieszczany w zapytaniu.

6.6.5. Metoda [doValidationFormulaire]

Metoda ta przetwarza zapytanie nr 2 [POST /personne2/main], w którym przesłane parametry to [action, txtNom, txtAge]. Jej kod wygląda następująco:

     // walidacja formularza
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
         // pobieranie parametrów
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
         // i zapisuje się je w sesji
        HttpSession session = request.getSession(true);        
        session.setAttribute("nom", nom);
        session.setAttribute("age", age);
         // sprawdzanie parametrów
        ArrayList<String> erreursAppel = new ArrayList<String>();
         // nazwa nie może być pusta
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
         // wiek musi być liczbą całkowitą >=0
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
         // czy występują błędy w parametrach?
        if (erreursAppel.size() != 0) {
             // wysyłamy stronę z komunikatem o błędzie
            request.setAttribute("erreurs", erreursAppel);
            request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            return;
        }
         // parametry są poprawne – wysyłamy stronę odpowiedzi
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        request.setAttribute("lienRetourFormulaire", (String)params.get("lienRetourFormulaire"));
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
  • wiersze 5–6: z żądania klienta pobierane są wartości parametrów „txtNom” i „txtAge”.
  • wiersze 8–10: wartości te są zapisywane w sesji, aby można je było odzyskać, gdy użytkownik kliknie link [Retour au formulaire] w widokach [réponse] i [erreurs].
  • wiersze 12–19: sprawdzana jest poprawność wartości obu parametrów
  • wiersze 21–28: jeśli któryś z parametrów jest nieprawidłowy, wyświetlany jest widok [erreurs(erreurs,lienRetourFormulaire)]. Przypomnijmy szablon tego widoku:

<%
// pobierane są dane z modelu
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs"); 
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
  • wiersze 30–34: jeśli oba pobrane parametry „txtNom” i „txtAge” mają prawidłowe wartości, wyświetlany jest widok [reponse(nom,age,lienRetourFormulaire)]. Należy pamiętać o szablonie widoku [reponse]:

<%
    // pobierane są dane z modelu
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
  String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>

6.6.6. Metoda [doRetourFormulaire]

Metoda ta przetwarza zapytanie nr 3 [GET /personne2/main?action=retourFormulaire]. Jej kod jest następujący:

// wyświetlanie wstępnie wypełnionego formularza
    void doRetourFormulaire(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
         // pobieranie sesji użytkownika
        HttpSession session = request.getSession(true);        
         // przygotowuje się szablon formularza
         // czy w sesji znajduje się imię?
        String nom = (String) session.getAttribute("nom");
        if (nom == null)
            session.setAttribute("nom", "");
         // czy w sesji znajduje się wiek?
        String age = (String) session.getAttribute("age");
        if (age == null)
            session.setAttribute("age", "");
         // urlAction
        request.setAttribute("urlAction", (String)params.get("urlControleur"));
         // wyświetla się formularz
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }

Po zakończeniu działania tej metody należy wyświetlić widok [formulaire], wstępnie wypełniony ostatnimi danymi wprowadzonymi przez użytkownika. Przypomnijmy szablon widoku [formulaire]:


<%
    // pobieramy dane z szablonu
  String nom=(String)session.getAttribute("nom");
  String age=(String)session.getAttribute("age");
  String urlAction=(String)request.getAttribute("urlAction");
%>

Metoda [doRetourFormulaire] musi zatem odtworzyć poprzedni szablon.

  • wiersz 4: pobieramy sesję, w której kontroler zapisał wprowadzone wartości (imię, wiek).
  • wiersz 7: pobieramy imię z sesji
  • wiersze 8–9: jeśli nie ma go w sesji, umieszczamy go tam z pustą wartością. Taki przypadek nie powinien wystąpić podczas normalnego działania aplikacji, ponieważ akcja [retourFormulaire] zawsze następuje po akcji [validationFormulaire], a więc po zapisaniu wprowadzonych danych w sesji. Sesja może jednak wygasnąć, ponieważ ma ograniczony czas trwania, często wynoszący kilkadziesiąt minut. W takim przypadku w wierszu 4 utworzono nową sesję, w której nie ma jeszcze nazwy. W nowej sesji umieszcza się zatem pustą nazwę.
  • wiersze 11–13: podobnie postępuje się w przypadku wieku
  • jeśli pominąć problem wygasłej sesji, wówczas wiersze 3–13 są zbędne. Elementy [nom,age] z modelu znajdują się już w sesji. Nie ma więc potrzeby ponownego ich tam umieszczania.
  • wiersz 15: ustalamy wartość elementu [urlAction] z szablonu

6.7. Tests

Uruchom lub ponownie uruchom serwer Tomcat. Wprowadź adres URL [http://localhost:8080/personne2], a następnie powtórz testy przedstawione w przykładzie w paragrafie 6.1.