Skip to content

5. MVC-Webanwendung [person] – Version 1

5.1. Die Ansichten der Anwendung

Die Anwendung verwendet das Formular aus den vorherigen Beispielen. Die erste Seite der Anwendung sieht wie folgt aus:

Image

Wir werden diese Ansicht als [form]-Ansicht bezeichnen. Sind die Eingaben korrekt, werden sie in einer Ansicht angezeigt, die als [response] bezeichnet wird:

Image

Sind die Eingaben falsch, werden die Fehler in einer Ansicht namens [Fehler] angezeigt:

Image

5.2. Anwendungsarchitektur

Die Webanwendung [person1] wird die folgende Architektur aufweisen:

Image

Es handelt sich um eine einstufige Architektur: Es gibt keine [Business]- oder [DAO]-Schicht, sondern nur eine [Web]-Schicht. [ServletPersonne] ist der Anwendungscontroller, der alle Client-Anfragen verarbeitet. Um auf diese Anfragen zu reagieren, verwendet er eine der drei Ansichten [Formular, Antwort, Fehler].

Wir müssen festlegen, wie der [ServletPersonne]-Controller die Aktion bestimmt, die er beim Empfang einer Benutzeranfrage ausführen muss. Eine Client-Anfrage ist ein HTTP-Stream, der sich je nachdem, ob er mit einem GET- oder POST-Befehl gestellt wird, unterscheidet.

GET-Anfrage

In diesem Fall sieht der HTTP-Stream wie folgt aus:

GET /URL 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
[ligne vide]

Zeile 1 gibt die angeforderte URL an, zum Beispiel:

GET /personne1/ HTTP/1.1

Diese URL kann verwendet werden, um die auszuführende Aktion anzugeben. Es stehen verschiedene Methoden zur Verfügung:

  1. Ein URL-Parameter gibt die Aktion an, zum Beispiel [/app?action=add&id=4]. Hier teilt der Parameter [action] dem Controller mit, welche Aktion angefordert wird.
  2. Das letzte Element der URL gibt die Aktion an, zum Beispiel [/app/add?id=4]. Hier wird das letzte Element der URL [/add] vom Controller verwendet, um die auszuführende Aktion zu bestimmen.

Es sind auch andere Lösungen möglich. Die beiden oben genannten sind gängig.

POST-Anfrage

In diesem Fall sieht der HTTP-Ablauf wie folgt aus:

POST /URL 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
Referer: http://localhost:8080/personne1/main
Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9
Content-Type: application/x-www-form-urlencoded
Content-Length: 43
[ligne vide]
txtNom=&txtAge=&action=validationFormulaire

Zeile 1 gibt die angeforderte URL an, zum Beispiel:

POST /personne1/main HTTP/1.1

Diese URL kann verwendet werden, um die auszuführende Aktion anzugeben, genau wie bei GET. Im Fall von GET war der Parameter [action] in der URL enthalten. Dies kann auch hier der Fall sein, wie in:

POST /appli?action=ajouter&id=4 HTTP/1.1

Der Parameter [action] kann jedoch auch in den gesendeten Parametern enthalten sein (Zeile 15 oben), wie in:

POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4

Im Folgenden werden wir diese verschiedenen Techniken nutzen, um dem Controller mitzuteilen, was er tun soll:

  • Fügen Sie den Aktionsparameter in die angeforderte URL ein:
POST /appli?action=ajouter&id=4 HTTP/1.1
  • Senden Sie den Aktionsparameter:
POST /appli HTTP/1.1
...
[ligne vide]
action=ajouter&id=4
  • Verwende das letzte Element der URL als Aktionsnamen:
POST /appli/ajouter?id=4 HTTP/1.1

5.3. Das Eclipse-Projekt

Um das Eclipse-Projekt [mvc-personne-01] für die Webanwendung [personne1] zu erstellen, befolgen Sie die in Abschnitt 3.1 beschriebene Vorgehensweise.

Image

Wir behalten den Standardkontext [mvc-personne-01] nicht bei. Wir wählen [personne1], wie unten gezeigt:

Image

Das Ergebnis sieht wie folgt aus:

Image

Wenn Sie den Kontext der Webanwendung ändern möchten, verwenden Sie die Option [Rechtsklick auf das Projekt -> Eigenschaften -> J2EE]:

Image

Geben Sie den neuen Kontext unter [1] ein.

Wir erstellen einen Unterordner [vues] im Ordner [WEB-INF]: [Rechtsklick auf WEB-INF -> Neu -> Ordner]:

Das neue Projekt sieht nun wie folgt aus:

Image

Nach Fertigstellung wird das Projekt so aussehen:

Image

  • Der Controller [ServletPersonne] befindet sich im Ordner [src]
  • Die JSP-Seiten für die Ansichten [Formular, Antwort, Fehler] befinden sich im Ordner [WEB-INF/vues], wodurch verhindert wird, dass der Benutzer direkt darauf zugreifen kann, wie im folgenden Beispiel gezeigt:

Image

Wir werden nun die verschiedenen Komponenten der Webanwendung [/personne1] beschreiben. Der Leser ist eingeladen, diese beim Lesen selbst zu erstellen.

5.4. Konfiguration der Webanwendung [person1]

Die Datei web.xml für die Anwendung /person1 sieht wie folgt aus:


<?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-01</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>
    </servlet>
    <!--  Mapping ServletPersonne-->
    <servlet-mapping>
        <servlet-name>personne</servlet-name>
        <url-pattern>/main</url-pattern>
    </servlet-mapping>
    <!--  welcome files -->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
 

Was steht in dieser Konfigurationsdatei?

  • Zeilen 34–37: Die URL /main wird von dem Servlet namens „person“ verarbeitet
  • Zeilen 10–13: Das Servlet namens „person“ ist eine Instanz der Klasse [ServletPersonne]
  • Zeilen 14–19: Definieren einen Konfigurationsparameter namens [urlResponse]. Dies ist die URL der Ansicht [response].
  • Zeilen 20–25: Definieren einen Konfigurationsparameter namens [urlErrors]. Dies ist die URL der Ansicht [errors].
  • Zeilen 26–31: Definieren Sie einen Konfigurationsparameter namens [urlForm]. Dies ist die URL der Ansicht [form].
  • Zeile 40: [index.jsp] ist die Startseite der Anwendung.

Die URLs der JSP-Seiten für die Ansichten [form, response, errors] werden jeweils durch einen Konfigurationsparameter definiert. Dadurch können sie verschoben werden, ohne dass die Anwendung neu kompiliert werden muss.

Wenn der Benutzer die URL [/person1] aufruft, sendet die Datei [index.jsp] die Antwort (Startseitendatei, Zeile 40). Diese Datei befindet sich im Stammverzeichnis des Ordners [WebContent]:

Image

Ihr Inhalt lautet wie folgt:


<%@ 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("/personne1/main");
%>

Die Seite [index.jsp] leitet den Client einfach zur URL [/person1/main] weiter. Wenn der Browser also die URL [/person1] anfordert, sendet [index.jsp] ihm die folgende HTTP-Antwort:

1
2
3
4
5
6
7
HTTP/1.x 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=9F5E5BFA29643FC6B1601EEED907E1F9; Path=/personne1
Location: http://localhost:8080/personne1/main
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 0
Date: Thu, 18 May 2006 15:45:23 GMT
  • Zeile 1: HTTP/1.1-Antwort, um den Server anzuweisen, zu einer anderen URL umzuleiten
  • Zeile 4: Die URL, zu der der Browser umleiten soll

Nach dieser Antwort fordert der Browser die URL [/person1/main] wie angegeben an (Zeile 4). Die Datei [web.xml] für die Anwendung [/person1] legt fest, dass diese Anfrage vom Controller [ServletPersonne] bearbeitet wird (Zeilen 35–36).

5.5. Der View-Code

Wir beginnen mit der Erstellung der Webanwendung, indem wir ihre Ansichten erstellen. Diese helfen dabei, die Anforderungen des Benutzers an die grafische Oberfläche zu definieren, und können ohne den Controller getestet werden.

5.5.1. Die [form]-Ansicht

Diese Ansicht ist für das Formular zur Eingabe von Name und Alter vorgesehen:

Image

HTML
HTML-Typ
Name
Rolle
1
<input type="text">
txtName
Name eingeben
2
<input type="text">
txtAge
Alter eingeben
3
<input type="submit">
 
Sende die eingegebenen Werte an den Server unter der URL /person1/main
4
<input type="reset">
 
um die Seite in den Zustand zurückzusetzen, in dem sie ursprünglich vom Browser empfangen wurde
5
<input type="button">
 
um den Inhalt der Eingabefelder [1] und [2] zu löschen

Es wird von der JSP-Seite [formulaire.jsp] generiert. Die Vorlage besteht aus den folgenden Elementen:

  • [name]: ein Name (String), der in den Sitzungsattributen unter dem Schlüssel „name“ zu finden ist
  • [age]: ein Alter (String), das in den Sitzungsattributen unter dem Schlüssel „age“ zu finden ist

Die Ansicht [form] wird aufgerufen, wenn der Benutzer die URL [/person1/main] anfordert, d. h. die URL des Controllers [ServletPersonne]. Der Code für die JSP-Seite [formulaire.jsp], die die Ansicht [form] generiert, lautet wie folgt:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
      <title>Personne - formulaire</title>
  </head>
  <body>
      <center>
        <h2>Personne - formulaire</h2>
      <hr>
      <form 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>
 
  • Zeilen 6–7: Die JSP-Seite beginnt damit, die Elemente [name, age] ihres Modells aus der Anfrage abzurufen. Im normalen Anwendungsbetrieb erstellt der Controller [ServletPersonne] dieses Modell.
  • Zeilen 18–38: Die JSP-Seite generiert ein HTML-Formular (Tag <form>)
  • Zeile 18: Das Tag <form> enthält kein „action“-Attribut, um die URL anzugeben, die die über die Schaltfläche [Submit] (Zeile 32) übermittelten Werte verarbeitet. Die Formularwerte werden dann an die URL gesendet, von der das Formular abgerufen wurde, d. h. an die URL des [ServletPersonne]-Controllers. Somit wird dieser Controller sowohl zur Generierung des ursprünglich per GET-Anfrage angeforderten leeren Formulars als auch zur Verarbeitung der eingegebenen Daten verwendet, die über die Schaltfläche [Submit] an ihn gesendet werden.
  • Die gesendeten Werte sind die der HTML-Felder [txtName] (Zeile 22), [txtAge] (Zeile 26) und [action] (Zeile 37). Dieser letzte Parameter ermöglicht es dem Controller zu erkennen, was er tun muss.
  • Bei der ersten Anzeige des Formulars werden die Eingabefelder [txtName] und [txtAge] mit den Variablen [name] (Zeile 22) bzw. [age] (Zeile 26) initialisiert. Diese Variablen beziehen ihre Werte aus den Request-Attributen (Zeilen 6–7), von denen bekannt ist, dass sie vom Servlet initialisiert werden. Es ist also das Servlet, das den Anfangsinhalt der Eingabefelder des Formulars festlegt.
  • Zeile 33: Die Schaltfläche [Reset] vom Typ [reset] versetzt das Formular in den Zustand zurück, in dem es sich befand, als der Browser es empfangen hat.
  • Zeile 34: Die Schaltfläche [Clear] vom Typ [reset] hat derzeit keine Funktion.

Im weiteren Verlauf werden wir diese Ansicht als [form(name, age)]-Ansicht bezeichnen, wenn wir sowohl den Namen der Ansicht als auch ihr Modell angeben möchten. Beachten Sie außerdem, dass beim Klicken des Benutzers auf die Schaltfläche [Submit] die Parameter [txtName, txtAge] an die URL [/person1/main] gesendet werden.

5.5.2. Die Ansicht [response]

Diese Ansicht zeigt die im Formular eingegebenen Werte an, sofern diese gültig sind:

Image

Sie wird von der JSP-Seite [reponse.jsp] generiert. Ihre Vorlage besteht aus den folgenden Elementen:

  • [name]: ein Name (String), der in den Sitzungsattributen zu finden ist und dem Schlüssel „name“ zugeordnet ist
  • [age]: ein Alter (String), das in den Sitzungsattributen zu finden ist und dem Schlüssel „age“ zugeordnet ist

Der Code für die JSP-Seite [reponse.jsp] lautet wie folgt:


<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
 
<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>      
  </body>
</html>
 
  • Zeilen 6–7: Die JSP-Seite beginnt damit, die Elemente [name, age] ihres Modells aus der Anfrage abzurufen. Im normalen Anwendungsbetrieb erstellt der Controller [ServletPersonne] dieses Modell.
  • Die Modellelemente [name, age] werden dann in den Zeilen 20 und 24 angezeigt

Anschließend bezeichnen wir diese Ansicht als die Ansicht [response(name, age)].

5.5.3. Die Ansicht [errors]

Diese Ansicht meldet Eingabefehler in folgender Form:

Image

Sie wird von der JSP-Seite [errors.jsp] generiert. Ihr Modell besteht aus den folgenden Elementen:

  • [errors]: eine Liste (ArrayList) von Fehlermeldungen, die in den Request-Attributen zu finden sind und dem Schlüssel „errors“ zugeordnet sind

Der Code für die JSP-Seite [errors.jsp] lautet wie folgt:


<%@ 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" %>
 
<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
 
<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");
        }//for
      %>
    </ul>
  </body>
</html>
 
  • Zeile 8: Die JSP-Seite beginnt damit, das Element [errors] aus ihrem Modell in der Anfrage abzurufen. Dieses Element stellt ein ArrayList-Objekt dar, das String-Elemente enthält. Diese Elemente sind Fehlermeldungen. Während des normalen Anwendungsbetriebs erstellt der [ServletPersonne]-Controller dieses Modell.
  • Zeilen 18–22: Zeigen die Liste der Fehlermeldungen an. Dazu müssen wir Java-Code innerhalb des HTML-Hauptteils der Seite schreiben. Wir sollten stets darauf achten, dies auf ein Minimum zu beschränken, um den HTML-Code übersichtlich zu halten. Wir werden später sehen, dass es Lösungen gibt, um die Menge an Java-Code in JSP-Seiten zu reduzieren.
  • Zeile 4: Beachten Sie das Import-Tag für die von der JSP-Seite benötigten Pakete

Wir werden diese Ansicht als die [errors(errors)]-Ansicht bezeichnen.

5.6. Testen von Views

Es ist möglich, die Gültigkeit von JSP-Seiten zu testen, ohne den Controller geschrieben zu haben. Dazu müssen zwei Bedingungen erfüllt sein:

  • Sie müssen in der Lage sein, sie direkt von der Anwendung aus anzufordern, ohne den Controller zu durchlaufen
  • Die JSP-Seite muss das Modell selbst initialisieren, das normalerweise vom Controller erstellt würde

Um diese Tests durchzuführen, duplizieren wir die JSP-Seiten der Ansichten im Ordner [/WebContent/JSP] des Eclipse-Projekts:

Image

Anschließend werden die Seiten im JSP-Ordner wie folgt geändert:

[form.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  request.setAttribute("nom","tintin");
  request.setAttribute("age","30");
%>
 
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
    
<html>
    <head>
...

Die Zeilen 3–7 wurden hinzugefügt, um die für die Zeilen 11–12 erforderliche Vorlage zu erstellen.

[reponse.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  request.setAttribute("nom","milou");
  request.setAttribute("age","10");
%>
 
<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
 
    
<html>
    <head>
...

Die Zeilen 3–7 wurden hinzugefügt, um die in den Zeilen 11–12 von der Seite benötigte Vorlage zu erstellen.

[errors.jsp]:


...
 
<%
  // -- test : on crée le modèle de la page
  ArrayList<String> erreurs1=new ArrayList<String>();
  erreurs1.add("erreur1");
  erreurs1.add("erreur2");
  request.setAttribute("erreurs",erreurs1);
%>
 
<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
 
    
<html>
    <head>
...

Die Zeilen 3–9 wurden hinzugefügt, um das in Zeile 13 geforderte Modell zu erstellen.

Starten Sie Tomcat, falls Sie dies noch nicht getan haben, und rufen Sie dann die folgenden URLs auf:

 

Wir erhalten die erwarteten Ansichten. Da wir nun ein angemessenes Vertrauen in die JSP-Seiten der Anwendung haben, können wir mit der Erstellung des Controllers [ServletPersonne] fortfahren.

5.7. Der [ServletPersonne]-Controller

Nun muss nur noch der Kern unserer Webanwendung geschrieben werden: der Controller. Seine Aufgabe ist es:

  • die Anfrage des Clients abzurufen,
  • die vom Client angeforderte Aktion zu verarbeiten,
  • die entsprechende Ansicht als Antwort zu senden.

Der Controller [ServletPersonne] wird die folgenden Aktionen ausführen:

Anfrage
Anfrage
Herkunft
Verarbeitung
1
[GET /person1/hand]
Vom Benutzer eingegebene URL
- die leere [Formular]-Ansicht senden
2
[POST /person1/hand]
mit den Parametern [txtName,
txtAge, action]
klicken Sie auf die
[Absenden]-Schaltfläche im
[Formular]
– Überprüfen Sie die Werte der Parameter [txtName, txtAge]
- Wenn sie falsch sind, sende die Ansicht [errors(errors)]
- wenn sie korrekt sind, sende die Ansicht [response(name,age)]

Die Anwendung startet, wenn der Benutzer die URL [/person1/main] aufruft. Gemäß der Datei [web.xml] der Anwendung (siehe Abschnitt 5.4) wird diese Anfrage von einer Instanz der Klasse ServletPersonne bearbeitet, die wir nun beschreiben werden.

5.7.1. Controller-Grundgerüst

Der Code für den [ServletPersonne]-Controller lautet wie folgt:

package istia.st.servlets.personne;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

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

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

    // initial view display
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
...
    }

    // form validation
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
...
    }

    // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        // we hand over to GET
        doGet(request, response);
    }
}
  • Zeilen 20–22: Die [init]-Methode, die beim ersten Laden des Servlets ausgeführt wird
  • Zeilen 25–28: Die Methode [doGet], die vom Webserver aufgerufen wird, wenn eine GET-Anfrage an die Anwendung gestellt wird
  • Zeilen 42–46: Die [doPost]-Methode, die vom Webserver aufgerufen wird, wenn eine POST-Anfrage an die Anwendung gestellt wird. Wie gezeigt, wird dies ebenfalls von der [doGet]-Methode (Zeile 45) abgewickelt.
  • Zeilen 31–33: Die Methode [doInit] verarbeitet die Aktion Nr. 1 [GET /person1/main]
  • Zeilen 36–39: Die Methode [doValidationFormulaire] verarbeitet Aktion Nr. 2 [POST /person1/main] mit den übermittelten Parametern [txtName, txtAge, action].

Wir werden nun die verschiedenen Methoden des Controllers beschreiben

5.7.2. Initialisierung des Controllers

Wenn die Controller-Klasse vom Servlet-Container geladen wird, wird ihre Methode [init] ausgeführt. Dies geschieht nur einmal. Sobald der Controller in den Speicher geladen ist, verbleibt er dort und verarbeitet Anfragen von verschiedenen Clients. Jeder Client wird von einem separaten Ausführungsthread bearbeitet, sodass die Methoden des Controllers gleichzeitig von verschiedenen Threads ausgeführt werden. Beachten Sie, dass der Controller aus diesem Grund keine Felder haben darf, die von seinen Methoden geändert werden könnten. Seine Felder müssen schreibgeschützt sein. Sie werden durch die [init]-Methode initialisiert, was deren Hauptaufgabe ist. Diese Methode hat die einzigartige Eigenschaft, dass sie nur einmal von einem einzigen Thread ausgeführt wird. Daher gibt es keine Probleme mit dem gleichzeitigen Zugriff auf die Felder des Controllers innerhalb dieser Methode. Der Zweck der [init]-Methode besteht darin, die von der Webanwendung benötigten Objekte zu initialisieren, die von allen Client-Threads im schreibgeschützten Modus gemeinsam genutzt werden. Diese gemeinsam genutzten Objekte können an zwei Stellen platziert werden:

  • den privaten Feldern des Controllers
  • im Ausführungskontext der Anwendung (ServletContext)

Der Code für die [init]-Methode des [ServletPersonne]-Controllers lautet wie folgt:

package istia.st.servlets.personne;

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

    // init
    @SuppressWarnings("unchecked")
    public void init() throws ServletException {
        // retrieve servlet initialization parameters
        ServletConfig config = getServletConfig();
        // other initialization parameters are processed
        String valeur=null;
        for(int i=0;i<paramètres.length;i++){
            // parameter value
            valeur=config.getInitParameter(paramètres[i]);
            // present parameter?
            if(valeur==null){
                // we note the error
                erreursInitialisation.add("Le paramètre ["+paramètres[i]+"] n'a pas été initialisé");
            }else{
                // parameter value is stored
                params.put(paramètres[i],valeur);
            }
            // the [errors] view url has a special treatment
            urlErreurs = config.getInitParameter("urlErreurs");
            if (urlErreurs == null)
                throw new ServletException(
                        "Le paramètre [urlErreurs] n'a pas été initialisé");
        }
    }
...
}
  • Zeile 16: Die Konfiguration der Webanwendung wird abgerufen, d. h. der Inhalt der Datei [web.xml]
  • Zeilen 19–29: Abruf der Servlet-Initialisierungsparameter, deren Namen im Array [parameters] in Zeile 9 definiert sind
  • Zeile 21: Der Parameterwert wird abgerufen
  • Zeile 25: Fehlt der Parameter, wird der Fehler zur anfänglich leeren Fehlerliste [initializationErrors] (Zeile 8) hinzugefügt.
  • Zeile 28: Ist der Parameter vorhanden, wird er zusammen mit seinem Wert im zunächst leeren Wörterbuch [params] (Zeile 10) gespeichert.
  • Zeilen 31–35: Der Parameter [urlErrors] muss vorhanden sein, da er die URL der Ansicht [errors] angibt, die etwaige Initialisierungsfehler anzeigen kann. Falls er nicht existiert, wird die Anwendung durch Auslösen einer [ServletException] beendet (Zeile 33).

5.7.3. Die [doGet]-Methode

Die Methode [doGet] verarbeitet sowohl GET- als auch POST-Anfragen an das Servlet, da die Methode [doPost] zur Methode [doGet] umleitet. Ihr Code lautet wie folgt:

package istia.st.servlets.personne;

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

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

        // check how the servlet was initialized
        if (erreursInitialisation.size() != 0) {
            // we hand over to the error page
            request.setAttribute("erreurs", erreursInitialisation);
            getServletContext().getRequestDispatcher(urlErreurs).forward(
                    request, response);
            // end
            return;
        }

        // retrieve the request sending method
        String méthode=request.getMethod().toLowerCase();
        // retrieve the action to be executed
        String action=request.getParameter("action");
        // action?
        if(action==null){
            action="init";
        }
        // execution action
        if(méthode.equals("get") && action.equals("init")){
            // start application
            doInit(request,response);
            return;
        }
        if(méthode.equals("post") && action.equals("validationFormulaire")){
            // validation of input form
            doValidationFormulaire(request,response);
            return;
        }
        // other cases
        doInit(request,response);
    }

    // post
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        // we hand over to GET
        doGet(request, response);
    }
}
  • Zeilen 18–25: Wir prüfen, ob die Liste der Initialisierungsfehler leer ist. Ist dies nicht der Fall, zeigen wir die Ansicht [errors(initializationErrors)] an, die die Fehler meldet.

Um diesen Code zu verstehen, müssen Sie sich an die [errors]-Ansichtsvorlage erinnern:

<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>

Die Ansicht [errors] erwartet einen Schlüssel namens „errors“ in der Anfrage. Der Controller erstellt diesen Schlüssel in Zeile 20.

  • Zeile 28: Wir ermitteln die [get]- oder [post]-Methode, die der Client für die Anfrage verwendet hat
  • Zeile 30: Wir rufen den Wert des Parameters [action] aus der Anfrage ab. Zur Erinnerung: In unserer Anwendung enthält nur Anfrage Nr. 2 [POST /person1/main] den Parameter [action]. In dieser Anfrage hat er den Wert [validationFormulaire].
  • Zeilen 31–34: Wenn der Parameter [action] nicht vorhanden ist, weisen wir ihm den Wert „init“ zu. Dies ist bei der ersten Anfrage Nr. 1 [GET /person1/main] der Fall.
  • Zeilen 36–40: Verarbeitung der Anfrage Nr. 1 [GET /person1/main].
  • Zeilen 41–45: Verarbeitung der Anfrage Nr. 2 [POST /person1/main].
  • Zeile 47: Wenn keiner der beiden vorherigen Fälle zutrifft, verfahren wir so, als befänden wir uns in Fall Nr. 1

5.7.4. Die Methode [doInit]

Diese Methode verarbeitet Anfrage Nr. 1 [GET /person1/main]. Für diese Anfrage muss sie die leere Ansicht [form(name, age)] zurückgeben. Der Code lautet wie folgt:

package istia.st.servlets.personne;
...

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

...    
    // initial view display
    void doInit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        // send the empty form
        request.setAttribute("nom", "");
        request.setAttribute("age", "");
        getServletContext().getRequestDispatcher((String)params.get("urlFormulaire")).forward(
                request, response);
        return;
    }
...
}
  • Zeilen 18–19: Die Ansicht [form] wird angezeigt. Erinnern Sie sich an das von dieser Ansicht erwartete Modell:

<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
  • Zeilen 16–17: Das Modell [name, age] der Ansicht [form] wird mit leeren Zeichenfolgen initialisiert.

5.7.5. Die Methode [doValidationForm]

Diese Methode verarbeitet die Anfrage Nr. 2 [POST /person1/main], bei der die übermittelten Parameter [action, txtName, txtAge] lauten. Der Code lautet wie folgt:

package istia.st.servlets.personne;

...
@SuppressWarnings("serial")
public class ServletPersonne extends HttpServlet {
    // instance parameters
    private String urlErreurs = null;
    private ArrayList erreursInitialisation = new ArrayList<String>();
    private String[] paramètres={"urlFormulaire","urlReponse"};
    private Map params=new HashMap<String,String>();
...
    // form validation
    void doValidationFormulaire(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException{
        // parameters are retrieved
        String nom = request.getParameter("txtNom");
        String age = request.getParameter("txtAge");
        // parameter verification
        ArrayList<String> erreursAppel = new ArrayList<String>();
        // name must be non-empty
        nom = nom.trim();
        if (nom.equals(""))
            erreursAppel.add("Le champ [nom] n'a pas été rempli");
        // age must be an integer >=0
        if (!age.matches("^\\s*\\d+\\s*$"))
            erreursAppel.add("Le champ [age] est erroné");
        // errors in the parameters?
        if (erreursAppel.size() != 0) {
            // send error page
            request.setAttribute("erreurs", erreursAppel);
            getServletContext().getRequestDispatcher(urlErreurs).forward(request, response);
            return;
        }
        // parameters are correct - send response page
        request.setAttribute("nom", nom);
        request.setAttribute("age", age);
        getServletContext().getRequestDispatcher((String)params.get("urlReponse")).forward(request,
                response);
        return;
    }
...
}
  • Zeilen 16–17: Die Werte der Parameter „txtNom“ und „txtAge“ werden aus der Anfrage des Clients abgerufen.
  • Zeilen 19–26: Die Gültigkeit dieser beiden Parameter wird überprüft
  • Zeilen 28–33: Ist einer der Parameter fehlerhaft, wird die Ansicht [errors(callErrors)] angezeigt. Hier noch einmal die Vorlage für diese Ansicht:

<%
// on récupère les données du modèle
  ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");  
%>
  • Zeilen 35–38: Wenn die beiden abgerufenen Parameter „txtNom“ und „txtAge“ gültige Werte haben, wird die Ansicht [response(name, age)] angezeigt. Zur Erinnerung: Die Vorlage für die Ansicht [response] lautet:

<%
    // on récupère les données du modèle
  String nom=(String)request.getAttribute("nom");
  String age=(String)request.getAttribute("age");
%>
 

5.8. Tests

Fügen wir das Projekt [mvc-personne-01] gemäß der in Abschnitt 3.3 beschriebenen Vorgehensweise in die Tomcat-Anwendungen ein:

Image

Starten Sie Tomcat. Sobald dies geschehen ist, können wir die in Abschnitt 5.1 als Beispiele gezeigten Tests fortsetzen. Wir können weitere Tests hinzufügen. Beispielsweise können wir einen der Konfigurationsparameter urlXXX aus web.xml entfernen und das Ergebnis betrachten. Wie unten gezeigt, ist einer der Parameter in [web.xml] auskommentiert:


        <!-- 
            <init-param>
              <param-name>urlFormulaire</param-name>
              <param-value>
                /WEB-INF/vues/formulaire.jsp
              </param-value>
            </init-param>
        -->

Wir starten oder starten Tomcat neu und rufen die URL [http://localhost:8080/personne1/main] auf. Wir erhalten folgende Antwort:

Image