Skip to content

6. Formulare HTML

Bisher haben wir ein einziges Formular verwendet, das nur zwei Eingabefelder enthielt. Hier wollen wir nun ein Formular erstellen und bearbeiten, das die üblichen grafischen Komponenten (Optionsfelder, Kontrollkästchen, Eingabefelder, Comboboxen, Listen) nutzt.

6.1. Die Ansichten der Anwendung

Die Anwendung wird nur zwei Ansichten haben. Die erste zeigt ein leeres Formular:

QZXW2HTMLP000547ZQX 1 - formulaire

Image

Diese erste Ansicht mit dem Namen formulaire.jsp ermöglicht es uns, verschiedene Tags aus der Struts-HTML-Bibliothek zu implementieren. Der Benutzer füllt das Formular aus:

Image

Über die Schaltfläche [Envoyer] kann eine Bestätigung der eingegebenen Werte abgerufen werden. Dies ist die zweite Ansicht:

Image

Diese zweite Ansicht ermöglicht es uns, zwei weitere Tag-Bibliotheken zu nutzen: „struts-bean“ und „struts-logic“. Über den Link [Retour au formulaire] gelangen wir zurück zu dem Formular, wie es ausgefüllt wurde. Wir befinden uns dann wieder in der ersten Ansicht.

6.2. Die Architektur der Anwendung

  • Das Formular (Ansicht 1) wird durch ein dynamisches Struts-Objekt namens dynaFormulaire dargestellt, dessen Typ von DynaActionForm abgeleitet ist. Es wird von der Ansicht formulaire.jsp angezeigt.
  • Die Struts-Aktion InitFormulaireAction dient dazu, die für die Anzeige des Formulars erforderlichen Daten abzurufen
  • Das ausgefüllte Formular wird von der Aktion ForwardAction verarbeitet, die lediglich die Anfrage an die zweite Ansicht confirmation.jsp weiterleitet. Diese übernimmt die Anzeige der Formularwerte.

6.3. Die Konfiguration der Anwendung

6.3.1. Die Datei server.xml

Der Anwendungskontext wird /formulaire2 heißen. Daher fügen wir die folgende Zeile in die Tomcat-Datei server.xml ein:

    <Context path="/formulaire2" docBase="e:/data/serge/web/struts/formulaire2" />

Anschließend starten wir Tomcat gegebenenfalls neu, damit der neue Kontext berücksichtigt wird. Wir können die Gültigkeit des Kontexts überprüfen, indem wir die Seite URL unter http://localhost:8080/formulaire2 aufrufen:

Image

6.3.2. Die Datei web.xml

Die Konfigurationsdatei web.xml der Anwendung sieht wie folgt aus:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    <servlet>
      <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
      <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <taglib>
      <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
  </taglib>
  <taglib>
      <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
  </taglib>
  <taglib>
      <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
  </taglib>

</web-app>

An den bereits bekannten Konfigurationsdateien web.xml nehmen wir einige Änderungen vor:

  • Wir fügen zwei neue Tag-Bibliotheken hinzu: „struts-bean“ und „struts-logic“. Diese werden in der Ansicht confirmation.jsp verwendet. Die Ansicht formulaire.jsp nutzt hingegen die Bibliothek „struts-html“.

6.3.3. Die Datei struts-config.xml

Die Datei struts-config.xml sieht wie folgt aus:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>
    <form-beans>
        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
            <form-property name="opt" type="java.lang.String" initial="non"/>
            <form-property name="chk1" type="java.lang.String"/>
            <form-property name="chk2" type="java.lang.String"/>
            <form-property name="chk3" type="java.lang.String"/>            
            <form-property name="champSaisie" type="java.lang.String" initial=""/>
            <form-property name="mdp" type="java.lang.String" initial=""/>        
            <form-property name="boiteSaisie" type="java.lang.String" initial=""/>        
            <form-property name="combo" type="java.lang.String"/>
            <form-property name="listeSimple" type="java.lang.String"/>
            <form-property name="listeMultiple" type="java.lang.String[]"/>                
            <form-property name="secret" type="java.lang.String" initial="xxx"/>
            <form-property name="valeursCombo" type="java.lang.String[]" />
            <form-property name="valeursListeSimple" type="java.lang.String[]" />
            <form-property name="valeursListeMultiple" type="java.lang.String[]"/>                  
        </form-bean>            
    </form-beans>

    <action-mappings>
      <action
          path="/confirmation"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          parameter="/vues/confirmation.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />

      <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>

      <action
          path="/affiche"
          parameter="/vues/formulaire.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />

    </action-mappings>

        <message-resources 
      parameter="ApplicationResources"
        null="false"/>    

</struts-config>

Darin finden sich die drei Hauptabschnitte:

  • die Deklaration der Formulare im Abschnitt <form-beans>
  • die Deklaration der Aktionen im Abschnitt <action-mappings>
  • die Deklaration der Ressourcendatei im Abschnitt <message-ressources>

6.3.4. Die Formularobjekte (Beans) der Anwendung

Die Objekte, die zur Darstellung der HTML-Formulare der Anwendung verwendet werden, sind Objekte vom Typ ActionForm oder davon abgeleitete Typen (DynaActionForm, DynaValidatorForm, ...). Sie werden als Beans bezeichnet, da ihre Struktur den Regeln von JavaBeans folgt. In unserer Anwendung gibt es nur eine Formular-Bean, die den Namen dynaFormulaire trägt und vom Typ DynaActionForm abgeleitet ist. Sie wird in den folgenden Situationen verwendet:

  • die für die Anzeige der Ansicht Nr. 1 erforderlichen Daten enthalten
  • die Werte des Formulars aus Ansicht Nr. 1 abzurufen, wenn der Benutzer es absendet (submit)
  • die für die Anzeige der Ansicht Nr. 2 erforderlichen Daten enthalten

Die Struktur des Beans dynaFormulaire ist eng mit dem Formular der Ansicht Nr. 1 verknüpft. Sehen wir uns dieses einmal genauer an:

Nr.
Typ HTML
Rolle
1
<input name="opt" type="radio" value="ja">
<input name="opt" type="radio" value="nein">
Gruppe miteinander verknüpfter Radiobuttons (gleicher Name)
2
<input name="chk1" type="radio" value="on">
<input name="chk2" type="radio" value="on">
<input name="chk3" type="radio" value="on">
Gruppen von Kontrollkästchen
(nicht denselben Namen)
3
<input type="text" name="champSaisie" >
ein Eingabefeld
4
<input type="password" name="mdp">
ein Passwortfeld
5
<textarea name="boiteSaisie">...</textarea>
ein mehrzeiliges Eingabefeld
6
<select name="combo" size="1">..</select>
ein Dropdown-Menü
7
<select name="listeSimple" size="3">..</select>
eine Liste mit einer Auswahlmöglichkeit
8
<select name="listeMultiple" size="3" multiple>..</select>
eine Liste mit Mehrfachauswahl
9
<input type="button" value="Löschen"
onclick='effacerListe("listeSimple")'>
Schaltfläche zum Aufheben der Auswahl
die in listeSimple (7) ausgewählten Elemente
10
<input type="button" value="Löschen"
onclick='Liste löschen("listeMultiple")'>
Schaltfläche zum Aufheben der Auswahl
die in listeMultiple (8) ausgewählten Elemente
11
<input type="submit" value="Senden">
Absenden-Schaltfläche des Formulars
12
<input type="hidden" name="secret" value="...">
Ein verstecktes Feld

Es gibt verschiedene Fälle:

  1. Das Objekt dynaFormulaire dient dazu, die Werte des oben genannten Formulars HTML zu speichern, das über die Schaltfläche [Envoyer] übermittelt wird. Es muss daher dieselben Felder enthalten wie das Formular HTML. Der Feldtyp wird durch die folgende Regel festgelegt:
  • Wenn das Feld HTML nur einen Wert liefert, dann hat das Feld dynaFormulaire den Typ java.lang.String
  • Wenn das Feld HTML mehrere Werte liefert, hat das Feld in dynaFormulaire den Typ java.lang.String[]

Im obigen Formular HTML kann nur das Feld listeMultiple mehreren Werten zugeordnet werden (den vom Benutzer ausgewählten). Eine erste Definition des Objekts dynaFormulaire würde daher wie folgt lauten:

        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
            <form-property name="opt" type="java.lang.String" initial="non"/>
            <form-property name="chk1" type="java.lang.String"/>
            <form-property name="chk2" type="java.lang.String"/>
            <form-property name="chk3" type="java.lang.String"/>            
            <form-property name="champSaisie" type="java.lang.String" initial=""/>
            <form-property name="mdp" type="java.lang.String" initial=""/>        
            <form-property name="boiteSaisie" type="java.lang.String" initial=""/>        
            <form-property name="combo" type="java.lang.String"/>
            <form-property name="listeSimple" type="java.lang.String"/>
            <form-property name="listeMultiple" type="java.lang.String[]"/>                
            <form-property name="secret" type="java.lang.String" initial="xxx"/>
        </form-bean>            

Wie erfolgt die Befüllung von dynaFormulaire mit den vom Web-Client übermittelten Werten aus dem Formular HTML?

opt
Das Feld „opt“ erhält den Wert „ja“, wenn das Feld HTML <input type="radio" name="opt" value="ja"> angekreuzt wurde, und den Wert „nein“, wenn das Feld <input type="radio" name="opt" value="nein"> angekreuzt wurde.
chk1
Das Feld „chk1“ erhält den Wert „on“, wenn das Feld HTML <input name="chk1" type="radio" value="1"> ausgewählt wurde, andernfalls keinen Wert. Im letzteren Fall behält das Feld „chk1“ seinen vorherigen Wert bei.
chk2
ebenso
chk3
dasselbe
champSaisie
Das Feld champSaisie erhält den Text, den der Benutzer in das Feld HTML <input type="text" name="champSaisie"> eingegeben hat. Dieser Text kann gegebenenfalls die leere Zeichenfolge sein.
mdp
Das Feld „mdp“ erhält den vom Benutzer in das Feld HTML <input type="password" name="mdp"> eingegebenen Text. Dieser Text kann gegebenenfalls die leere Zeichenfolge sein.
boiteSaisie
Das Feld boiteSaisie erhält den vom Benutzer in das Feld HTML eingegebenen Text <textarea name="boiteSaisie">...</textarea>. Dieser Text bildet eine einzige Zeichenkette, die aus den vom Benutzer eingegebenen Zeilen besteht, die durch die Zeichenfolge „\r\n“ voneinander getrennt sind. Der resultierende Text kann gegebenenfalls die leere Zeichenkette sein.
combo
Das Kombinationsfeld erhält die vom Benutzer im Feld HTML <select name="combo" size="1">..</select> ausgewählte Option. Die ausgewählte Option ist diejenige, die im Kombinationsfeld angezeigt wird. Wenn die ausgewählte Option HTML vom Typ <option value="XX">YY</option> ist, erhält das Kombinationsfeld den Wert „XX“. Wenn die ausgewählte Option „HTML“ vom Typ <option>YY</option> ist, erhält das Kombinationsfeld den Wert „YY“.
listeSimple
Das Feld listeSimple erhält die vom Benutzer im Feld HTML <select name="listeSimple" size="..">..</select> ausgewählte Option, sofern eine vorhanden ist. Ist dies nicht der Fall, erhält das Feld listeSimple keinen Wert und behält seinen vorherigen Wert bei. Der tatsächlich dem Feld listeSimple zugewiesene Wert folgt den für das Kombinationsfeld angegebenen Regeln.
listeMultiple
Das Feld listeMultiple vom Typ String[] erhält die vom Benutzer im Feld HTML <select name="listeMultiple" size=".." multiple>..</select> ausgewählten Optionen, sofern vorhanden. Sind keine vorhanden, erhält das Array listeMultiple keinen Wert und sein Inhalt bleibt unverändert. Die tatsächlich dem Array listeMultiple zugewiesenen Werte folgen den für das Kombinationsfeld angegebenen Regeln.
secret
Das Feld „secret“ erhält den Wert XX aus dem Feld HTML <input type="hidden" name="secret" value="XX">. Dieser Text kann gegebenenfalls die leere Zeichenfolge sein.
  1. Das Objekt dynaFormulaire wird verwendet, um den Anfangsinhalt der Ansicht Nr. 1 festzulegen. Die Werte der vorherigen Felder werden für folgende Zwecke verwendet:
opt
muss den Wert „ja“ oder „nein“ haben, damit der Browser weiß, welches Optionsfeld ausgewählt werden soll
chk1
Wenn chk1 den Wert „on“ hat, wird das Kontrollkästchen aktiviert, andernfalls bleibt es deaktiviert
chk2
ebenso
chk3
dasselbe
champSaisie
Der Wert des Feldes wird im Eingabefeld angezeigt champSaisie
mdp
Der Wert des Feldes wird im Eingabefeld „mdp“ angezeigt
boiteSaisie
Der Wert des Feldes wird im Eingabefeld angezeigt boiteSaisie
combo
Der Wert dieses Feldes gibt an, welches Element der Combobox bei der Anzeige des Formulars ausgewählt sein soll
listeSimple
dasselbe
listeMultiple
Die Werte der Tabelle listeMultiple geben an, welche Elemente der Mehrfachauswahlliste bei der Anzeige des Formulars ausgewählt werden sollen
secret
Der Wert des Feldes wird dem Attribut „value“ des Feldes „secret“ zugewiesen.

Die Ansicht Nr. 1 benötigt weitere Informationen:

  • die Liste der Werte, die in der Kombinationsliste angezeigt werden sollen
  • die Liste der Werte, die in der Liste listeSimple angezeigt werden sollen
  • die Liste der Werte, die in der Liste listeMultiple angezeigt werden sollen

Es gibt mehrere Möglichkeiten, diese Informationen an die Ansicht zu übergeben. Zum Beispiel würden Arrays, die in der an die Ansicht übergebenen Abfrage enthalten sind, diesen Zweck erfüllen. Hier speichern wir diese Arrays in der Bean dynaFormulaire:

        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
            <form-property name="valeursCombo" type="java.lang.String[]" />
            <form-property name="valeursListeSimple" type="java.lang.String[]" />
            <form-property name="valeursListeMultiple" type="java.lang.String[]"/>                  
        </form-bean>            

Das Formular dynaFormulaire wird durch die Aktion /init initialisiert, die ein von Action abgeleitetes Objekt namens InitFormulaireAction aufruft. Dieses Objekt ist dafür zuständig, die drei für die Anzeige der drei Listen erforderlichen Arrays zu erstellen und sie in die Bean dynaFormulaire zu übertragen. Die Konfigurationsdatei weist dieser Bean einen Gültigkeitsbereich zu, der der Sitzung entspricht. Dies hat zur Folge, dass der Struts-Controller diese Bean in die Sitzung einfügt. Wir müssen sie somit zwischen zwei Anfrage-Antwort-Zyklen nicht neu generieren. Daher wird die Aktion /init nur einmal aufgerufen.

  1. Das Objekt dynaFormulaire wird ebenfalls verwendet, um den Inhalt der Ansicht Nr. 2 bereitzustellen. Diese beschränkt sich darauf, die Werte anzuzeigen.

6.3.5. Die Aktionen der Anwendung

Die Aktionen werden von Objekten vom Typ „Action“ oder davon abgeleiteten Objekten ausgeführt. Die Konfiguration der Aktionen erfolgt innerhalb der Tags <action-mappings>:

    <action-mappings>
      <action
          path="/confirmation"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          parameter="/vues/confirmation.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />

      <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>

      <action
          path="/affiche"
          parameter="/vues/formulaire.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />

    </action-mappings>

Es ist zu beachten, dass einer Aktion nicht immer ein Formular zugeordnet ist. Dies ist im obigen Beispiel bei der Aktion /affiche der Fall. Bevor wir jede Aktion im Detail betrachten, wollen wir noch einmal die Funktionsweise des Paares aus Aktion und zugehörigem Formular innerhalb eines <action>-Tags erläutern:

  • Eine Aktion beginnt mit einer Anfrage eines Web-Clients und endet mit dem Senden einer Antwortseite. Dies ist der Anfrage-Antwort-Zyklus zwischen Web-Client und Web-Server. Die Anfrage wird vom Struts-Controller vom Typ ActionServlet oder einem davon abgeleiteten Typ empfangen. Dieser Controller sendet auch die Antwort.
  • Die Formular-Bean vom Typ ActionForm oder einem davon abgeleiteten Typ wird erstellt, falls sie noch nicht existiert. Der Controller prüft, ob er ein Objekt mit dem Namen „name“ im durch „scope“ angegebenen Gültigkeitsbereich finden kann. Wenn ja, verwendet er es. Wenn nicht, erstellt er es und fügt es dem durch „scope“ angegebenen Gültigkeitsbereich hinzu, verknüpft mit dem durch „name“ angegebenen Attribut.

Im Beispiel der Aktion /init führt der Controller beispielsweise einen Aufruf von request.getSession().getAttribute("dynaFormulaire") durch, um festzustellen, ob dynaFormulaire bereits angelegt wurde oder nicht. Ist dies nicht der Fall, wird er es erstellen und mittels einer Anweisung wie request.getSession() in die Sitzung einfügen.setAttribute("dynaFormulaire", new DynaFormulaire(...)).

  • Der Controller sucht außerdem nach einem Action-Objekt des durch das Attribut „type“ angegebenen Typs. Findet er keines, erstellt er es; andernfalls verwendet er es.
  • Die Methode „reset“ des Formular-Beans wird aufgerufen. Dieses wird – außer bei seiner erstmaligen Erstellung – wiederverwendet. Es enthält dann Daten, die man möglicherweise „bereinigen“ möchte. Dies geschieht in der Methode „reset“ des Beans ActionForm oder eines davon abgeleiteten Beans.
  • Wenn die Aktion das Ziel eines gesendeten Formulars ist, werden die im Client-Request enthaltenen Formularwerte in die gleichnamigen Felder des Formular-Beans kopiert. Dabei ist zu beachten, dass die Methode „reset“ vor dieser Kopieraktion aufgerufen wurde.
  • Wenn in der Konfiguration das Attribut `validate="true"` angegeben ist, wird die Methode `validate` der Formular-Bean aufgerufen. Diese muss dann die Daten der Bean überprüfen. Diese Überprüfung findet meist nur dann statt, wenn das Formular gerade neue Daten über ein per POST übermitteltes Formular erhalten hat und die Gültigkeit dieser Daten überprüft werden soll. Diese Methode gibt dem Controller eine eventuelle Fehlerliste in einem Objekt vom Typ ActionErrors zurück.
  • Ist das Objekt ActionErrors nicht leer, lässt der Controller die durch das Attribut „input“ der Aktion angegebene Ansicht anzeigen.
  • Wenn keine Datenvalidierung angefordert wurde oder diese erfolgreich verlaufen ist, lässt der Controller die Methode `execute` des Objekts vom Typ `Action` oder eines davon abgeleiteten Typs ausführen, das der aktuellen Aktion zugeordnet ist. In dieser Methode wird die Anfrage des Web-Clients verarbeitet. Die Methode `execute` gibt ein Objekt vom Typ `ActionForward` zurück, das durch Schlüssel vom Typ Zeichenkette indiziert ist. Diese Schlüssel sind diejenigen, die durch die „forward“-Tags der konfigurierten Aktion deklariert wurden. In unserem Beispiel hat die Aktion /init ein einziges „forward“-Tag. Es ordnet den Schlüssel „afficherFormulaire“ der Ansicht formulaire.jsp zu.
  • Der Controller lässt die Ansicht anzeigen, der der empfangene Schlüssel zugeordnet ist. Diese Ansicht kann wiederum eine Aktion sein; in diesem Fall wird der vorherige Vorgang wiederholt.

Die Aktion /init

        <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>
  • Die Aktion /init findet normalerweise einmal während des ersten Anfrage-Antwort-Zyklus statt, wenn der Benutzer das URL-http://localhost:8080/formulaire2/init.do anfordert
  • das Objekt dynaFormulaire angelegt oder wiederverwendet wird. Es wird entsprechend dem Attribut „scope“ in die Sitzung übernommen (Wiederverwendung) oder dort abgelegt (Anlegen).
  • Seine Methode „reset“ wird aufgerufen. Was soll sie tun? Normalerweise werden die Felder des Objekts ActionForm auf Standardwerte zurückgesetzt. Nur in diesem Fall tun wir das nicht, da das Objekt dynaFormulaire in die Sitzung gesetzt wird (scope="session"). Die Felder von dynaFormulaire müssen daher ihre Werte beibehalten. Welche Werte hatten diese Felder bei der erstmaligen Erstellung des Objekts dynaFormulaire? Es gibt zwei Fälle:
  • Das Feld hat einen in der Konfigurationsdatei angegebenen Anfangswert:
            <form-property name="opt" type="java.lang.String" initial="non"/>

In diesem Fall legt der Struts-Controller dieses Feld mit diesem Anfangswert an.

  • Das Feld hat keinen in der Konfiguration festgelegten Anfangswert: Es gelten die Initialisierungsregeln von Java. Im Allgemeinen erhalten numerische Felder den Wert Null, Zeichenfolgen den Wert der leeren Zeichenfolge und alle anderen Objekte den Wert Null.

Sehen wir uns die ursprüngliche Konfiguration von dynaFormulaire an:

        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
            <form-property name="opt" type="java.lang.String" initial="non"/>
            <form-property name="chk1" type="java.lang.String"/>
            <form-property name="chk2" type="java.lang.String"/>
            <form-property name="chk3" type="java.lang.String"/>            
            <form-property name="champSaisie" type="java.lang.String" initial=""/>
            <form-property name="mdp" type="java.lang.String" initial=""/>        
            <form-property name="boiteSaisie" type="java.lang.String" initial=""/>        
            <form-property name="combo" type="java.lang.String"/>
            <form-property name="listeSimple" type="java.lang.String"/>
            <form-property name="listeMultiple" type="java.lang.String[]"/>                
            <form-property name="secret" type="java.lang.String" initial="xxx"/>
            <form-property name="valeursCombo" type="java.lang.String[]" />
            <form-property name="valeursListeSimple" type="java.lang.String[]" />
            <form-property name="valeursListeMultiple" type="java.lang.String[]"/>             
        </form-bean>            

Die Anfangswerte der Felder von dynaFormulaire nach seiner Erstellung lauten wie folgt:

Feld
Anfangswert
opt
„nein“
chk1, chk2, chk3
leere Zeichenfolge
champSaisie
leere Zeichenfolge
mdp
leere Zeichenkette
boiteSaisie
leere Zeichenfolge
combo
leere Zeichenfolge
listeSimple
leere Zeichenfolge
listeMultiple
Array aus leeren Zeichenfolgen
secret
„xxx“
valeursCombo, listeSimple, listeMultiple
Array mit leeren Zeichenfolgen
  • Man könnte sich vorstellen, dass die Methode „reset“ von dynaFormulaire Werte an die drei Arrays übergibt, die die drei Listen der Ansicht formulaire.jsp füllen sollen. Dies wäre hier möglich, da die Daten dieser drei Arrays willkürlich generiert werden. Der häufigste Fall ist jedoch, dass diese Daten aus dem Anwendungsmodell stammen, dem M von MVC. Um das Beispiel nicht zu verkomplizieren, wählen wir hier einen Mittelweg und lassen diese Werte durch die Aktion InitFormulaireAction generieren, also durch das C von MVC.
  • Es besteht keine Verpflichtung, eine Reset-Methode in dynaFormulaire zu schreiben, da die Klasse ActionForm, von der sie abgeleitet ist, über eine solche Methode verfügt, die nichts tut (keine Initialisierungen).
  • Sobald die Reset-Methode von dynaFormulaire aufgerufen wurde, prüft der Controller das Attribut „validate“ der Aktion. Hier hat es den Wert „false“. Die Validate-Methode von dynaFormulaire wird nicht aufgerufen.
  • Das Objekt InitFormulaireAction wird erstellt oder, falls es bereits existierte, wiederverwendet, und seine Methode „execute“ wird aufgerufen. Diese Methode weist den drei Arrays von dynaFormulaire valeursCombo, valeursListeSimple und valeursListeMultiple – beliebige Werte zu. Die Methode gibt ein ActionForward mit dem Schlüssel „afficherFormulaire“ zurück.
  • Der Controller lässt die Ansicht /vues/formulaire.jsp anzeigen, die über ein Forward-Tag der Aktion /init dem Schlüssel „afficherFormulaire“ zugeordnet wurde.

Die Aktion /confirmation

      <action
          path="/confirmation"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          parameter="/vues/confirmation.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
  • Die Aktion /confirmation wird ausgelöst, wenn der Benutzer in Ansicht Nr. 1 auf die Schaltfläche [Envoyer] klickt. Der Browser „sendet“ daraufhin das vom Benutzer ausgefüllte Formular an den Struts-Controller.
  • Das Objekt dynaFormulaire wird in die Sitzung aufgenommen
  • und seine reset-Methode wird aufgerufen. Sobald diese aufgerufen wurde, kopiert der Struts-Controller die Werte der vom Client übermittelten Formularfelder in die gleichnamigen Felder von dynaFormulaire. Sehen wir uns noch einmal die Liste der Felder dieses Objekts an und schauen wir uns an, wie diese Übertragung abläuft:
Feld
Zugehöriger Code von HTML
Feldwert
nach der Übernahme der Formularwerte
opt
<input type="radio" name="opt" value="ja">Ja
<input type="radio" name="opt" value="nein" checked="checked">Nein
– „Ja“ oder „Nein“, je nach ausgewähltem Optionsfeld
chk1
<input type="checkbox" name="chk1" value="on">
- „on“, wenn das Kontrollkästchen chk1 aktiviert wurde
- behält seinen vorherigen Wert bei, wenn das Kontrollkästchen „chk1“ nicht angekreuzt wurde
chk2
<input type="checkbox" name="chk2" value="on">
- „on“, wenn das Kontrollkästchen chk2 angekreuzt wurde
- behält seinen vorherigen Wert bei, wenn das Kontrollkästchen „chk2“ nicht angekreuzt wurde
chk3
<input type="checkbox" name="chk2" value="on">
- „on“, wenn das Kontrollkästchen chk3 aktiviert wurde
- behält den vorherigen Wert bei, wenn das Kontrollkästchen „chk3“ nicht angekreuzt wurde
champSaisie
<input type="text" name="champSaisie" value="">
- vom Benutzer in champSaisie eingegebener Wert
mdp
<input type="password" name="mdp" value="">
- vom Benutzer in „mdp“ eingegebener Wert
boiteSaisie
<textarea name="boiteSaisie"></textarea>
- vom Benutzer in „boiteSaisie“ eingegebener Wert
combo
<select name="combo">...</select>
- vom Benutzer in „combo“ ausgewählter Wert
listeSimple
<select name="listeSimple" size="3">...</select>
- vom Benutzer in listeSimple ausgewählter Wert
listeMultiple
<select name="listeMultiple" multiple="multiple" size="5">
- Array von Zeichenfolgen, das die vom Benutzer in listeMultiple ausgewählten Werte enthält
secret
<input type="hidden" name="secret" value="xxx">
- „xxx“.

Es gibt ein Problem mit Feldern, die in der vom Browser gesendeten Anfrage nicht unbedingt einen Wert erhalten. Dies gilt für die Kontrollkästchen chk1 bis chk3 sowie für die beiden Listen listeSimple und listeMultiple. In diesem Fall behalten diese Felder ihren vorherigen Wert bei, der im Verlauf des vorherigen Anfrage-Antwort-Zyklus erfasst wurde.

Betrachten wir zum Beispiel das Kontrollkästchen chk1 und nehmen wir an, dass der Benutzer dieses Kontrollkästchen im vorherigen Anfrage-Antwort-Zyklus aktiviert hatte. Der Browser hatte dann in der Parameterzeichenfolge seiner Anfrage die Information chk1="on" gesendet. Der Hersteller hat dem Feld chk1 von dynaFormulaire daher den Wert „on“ zugewiesen. Nehmen wir nun an, dass der Benutzer im aktuellen Zyklus das Kontrollkästchen chk1 nicht aktiviert. In diesem Fall sendet der Browser in der Parameterzeichenfolge der neuen Anfrage nicht etwa chk1="off", sondern gar nichts. Dadurch behält das Feld chk1 von dynaFormulaire seinen Wert „on“ bei und weist somit einen Wert auf, der nicht dem vom Benutzer validierten Formular entspricht. Um dieses Problem zu beheben, verwenden wir die Methode „reset“ von dynaFormulaire. In dieser Methode setzen wir die drei Felder chk1, chk2 und chk3 auf „off“. In unserem Beispiel für chk1: Wenn der Benutzer

  • das Kontrollkästchen chk1 ankreuzt. Dann sendet der Browser die Information chk1="on" und das Feld chk1 von dynaFormulaire wird auf „on“ gesetzt
  • das Kontrollkästchen chk1 nicht aktiviert. Dann sendet der Browser keinen Wert für das Feld chk1, das seinen vorherigen Wert „off“ beibehält. In beiden Fällen ist der im Feld chk1 von dynaFormulaire gespeicherte Wert korrekt.

Das Problem tritt bei den beiden Listen „listeSimple“ und „listeMultiple“ in gleicher Weise auf. Wenn in diesen Listen keine Option ausgewählt wurde, sind sie nicht in den Abfrageparametern enthalten und behalten daher ihre bisherigen Werte bei. In der Reset-Methode von dynaFormulaire setzen wir listeSimple auf eine leere Zeichenkette und listeMultiple auf ein Array von Zeichenketten der Länge 0 zurück.

  • Sobald die reset-Methode von dynaFormulaire aufgerufen wird, kopiert der Controller die Informationen, die ihm in der Client-Anfrage gesendet wurden, in die Felder von dynaFormulaire
  • Ein Objekt ForwardAction wird erstellt oder wiederverwendet und seine Methode „execute“ aufgerufen. ForwardAction ist eine vordefinierte Klasse, die ein Objekt ActionForward zurückgibt, das auf die durch das Attribut „parameter“ der Aktion definierte Ansicht verweist, hier /vues/confirmation.jsp.
  • Der Controller sendet diese Ansicht. Der Zyklus ist abgeschlossen.

Die Aktion /zeigt

      <action
          path="/affiche"
          parameter="/vues/formulaire.jsp"
          type="org.apache.struts.actions.ForwardAction"
      />
  • Die Aktion /anzeigen wird durch Anklicken des Links [Retour vers le formulaire] in Ansicht Nr. 2 ausgelöst.
  • Hier ist der Aktion kein Formular zugeordnet. Es wird daher sofort die Methode „execute“ eines Objekts ForwardAction aufgerufen, die ein Objekt ActionForward zurückgibt, das auf die Ansicht /vues/formulaire.jsp verweist.

6.3.6. Die Meldungsdatei der Anwendung

Der dritte Abschnitt der Datei struts-config.xml ist die Meldungsdatei:

        <message-resources 
          parameter="ApplicationResources"
            null="false"
      />    

Die Datei ApplicationResources.properties befindet sich im Verzeichnis WEB-INF/classes. Sie ist leer. Auch wenn sie leer ist, muss sie dennoch in der Konfigurationsdatei deklariert werden, da sonst die Struts-Bean-Tag-Bibliothek, auf die wir später noch eingehen werden, einen Fehler generiert. Diese Bibliothek wird von der Ansicht confirmation.jsp verwendet.

6.4. Der Code der Ansichten

6.4.1. Die Ansicht formulaire.jsp

Zur Erinnerung: Diese Ansicht wird in zwei Fällen angezeigt:

  • beim Aufruf der Aktion /init im ersten Anfrage-Antwort-Zyklus
  • beim Aufruf der Aktion /affiche in den folgenden Zyklen

Der Code der Ansicht formulaire.jsp lautet wie folgt:

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
  <head>
      <title>formulaire</title>
  </head>  
  <body background='<html:rewrite page="/images/standard.jpg"/>'>
      <h3>Formulaire Struts</h3>
    <hr>
    <html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
      <table border="0">
        <tr>
          <td>bouton radio</td>
          <td>
                        <html:radio name="dynaFormulaire" property="opt" value="oui">Oui</html:radio>
                        <html:radio name="dynaFormulaire" property="opt" value="non">Non</html:radio>                                            
          </td>
        </tr>
        <tr>
          <td>Cases à cocher</td>
          <td>
                        <html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
                        <html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox>
                        <html:checkbox name="dynaFormulaire" property="chk3">3</html:checkbox>                                                
          </td>
        </tr>
        <tr>
          <td>Champ de saisie</td>
          <td>
                        <html:text name="dynaFormulaire" property="champSaisie" />
          </td>
        </tr>
        <tr>
          <td>Mot de passe</td>
          <td>
              <html:password name="dynaFormulaire" property="mdp" />
          </td>
        </tr>
        <tr>
          <td>Boîte de saisie multilignes</td>
          <td>
              <html:textarea name="dynaFormulaire" property="boiteSaisie" />
          </td>
        </tr>
        <tr>
          <td>Combo</td>
          <td>
              <html:select name="dynaFormulaire" property="combo">
                            <html:options name="dynaFormulaire" property="valeursCombo"/>
                        </html:select>
          </td>
        </tr>
        <tr>
          <td>
                        <table>
                            <tr>
                                <td>Liste à sélection unique</td>
                            </tr>
                            <tr>
                                <td>
                                    <input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>
                                </td>
                            </tr>
                        </table>
          <td>
              <html:select name="dynaFormulaire" property="listeSimple" size="3">
                            <html:options name="dynaFormulaire" property="valeursListeSimple"/>                        
                        </html:select>
          </td>
        </tr>
        <tr>
                    <td>
                        <table>
                            <tr>
                                <td>Liste à sélection multiple</td>
                            </tr>
                            <tr>
                                <td>
                                    <input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>                                
                                </td>
                            </tr>
                        </table>
                    </td>
          <td>
              <html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
                            <html:options name="dynaFormulaire" property="valeursListeMultiple"/>                        
                        </html:select>
          </td>
        </tr>
      </table>
      <html:hidden name="dynaFormulaire" property="secret"/>
            <br>
            <hr>
            <html:submit>Envoyer</html:submit> 
    </html:form>
  </body>
</html>

Diese Seite JSP verwendet Tags aus der Struts-HTML-Bibliothek. Zur Erinnerung: Um eine Tag-Bibliothek zu verwenden, muss man:

  • sie in der Datei web.xml der Anwendung mit einem <tag-lib>-Tag deklarieren
  <taglib>
      <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
    <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
  </taglib>
  • den Code dieser Bibliothek an einer beliebigen Stelle im Verzeichnisbaum der Anwendung ablegen, hier WEB-INF/struts-html.tld
  • Deklarieren Sie die Verwendung dieser Bibliothek am Anfang der Seiten JSP, die sie nutzen:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

Die Ansicht formulaire.jsp verwendet Tags, die wir nun erläutern:

balise
<body background="<html:rewrite page="/images/standard.jpg"/>">
traduction HTML
<body background="/formulaire2/images/standard.jpg">
explication
Mit dem Tag „html:rewrite“ lässt sich der Name der Anwendung in URL umgehen. Es verfügt über ein Attribut:
page
URL – neu schreiben
Wie oben gezeigt, muss der Code des Attributs „background“ nicht neu geschrieben werden, wenn man beschließt, die Anwendung „formulaire3“ aufzurufen. Das Tag „html:rewrite“ generiert den neuen Code „HTML“
background="/formulaire3/images/standard.jpg"
balise
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
traduction HTML
<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">
explication
Mit dem HTML-Tag „html:form“ lässt sich das Formular-Tag „HTML“ generieren. Es verfügt über mehrere Attribute:
action
Struts-Aktion, an die das Formular gesendet werden soll – muss mit einer der in struts-config.xml definierten Aktionen übereinstimmen
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das die Werte des gesendeten Formulars geschrieben bzw. aus dem sie gelesen werden sollen. Fehlt dieses Attribut, wird das Formular verwendet, das der durch das Attribut „action“ definierten Aktion zugeordnet ist. Diese Information findet sich in der Konfigurationsdatei (Attribut „name“ der Aktion).
type
optional – Java-Klasse, die für das Formular instanziiert werden soll. Fehlt dieses Attribut, wird die Klasse verwendet, die der durch das Attribut „action“ definierten Aktion zugeordnet ist. Diese Information findet sich in der Konfigurationsdatei (Attribut „type“ der Aktion).
Man sieht, dass der generierte Code HTML standardmäßig die Methode POST verwendet. In eben diesem Code HTML wurde der Code URL der Aktion so umgeschrieben, dass ihm der Name der Anwendung als Präfix und „.do“ als Suffix vorangestellt bzw. angehängt wird.
balise
<html:radio name="dynaFormulaire" property="opt" value="ja">Ja</html:radio>
traduction HTML
<input type="radio" name="opt" value="oui">
explication
Das HTML-Tag „html:radio“ dient dazu, das Tag HTML <input type="radio" ...> zu generieren. Es unterstützt verschiedene Attribute:
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, die dem Radiobutton zugeordnet ist, zum Lesen und Schreiben.
value
optional – Wert, der dem Feld HTML zugewiesen werden soll
Der Text zwischen dem Start- und End-Tag ist der Text, der neben dem Optionsfeld angezeigt wird.
balise
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
traduction HTML
<input type="checkbox" name="chk1" value="on">
explication
Das HTML-Tag „html:checkbox“ dient dazu, das Tag HTML <input type="checkbox" ...> zu generieren. Es unterstützt verschiedene Attribute:
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, die dem Kontrollkästchen zugeordnet ist, mit Lese- und Schreibzugriff.
value
optional – Wert, der dem Feld HTML zugewiesen werden soll
Der Text zwischen dem Start- und End-Tag ist der Text, der neben dem Kontrollkästchen angezeigt wird.
balise
<html:text name="dynaFormulaire" property="champSaisie" />
traduction HTML
<input type="text" name="champSaisie" value="">
explication
Das HTML-Tag „html:text“ dient dazu, das Tag HTML <input type="text" ...> zu generieren. Es unterstützt verschiedene Attribute:
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, die dem Eingabefeld zum Lesen und Schreiben zugeordnet ist.
value
optional – Wert, der in das Feld HTML einzutragen ist
balise
<html:password name="dynaFormulaire" property="mdp" />
traduction HTML
<input type="password" name="mdp" value="">
explication
Das HTML-Tag „html:password“ dient dazu, das Tag „HTML <input type="password" ...>“ zu generieren. Es unterstützt verschiedene Attribute:
balise
<html:textarea name="dynaFormulaire" property="boiteSaisie" />
traduction HTML
<textarea name="boiteSaisie"></textarea>
explication
Das HTML-Tag „textarea“ dient dazu, das Tag HTML <textarea>...</textarea> zu generieren. Es unterstützt verschiedene Attribute:
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, das dem Passwortfeld zugeordnet ist und sowohl les- als auch schreibbar ist.
value
optional – Wert, der dem Feld „HTML“ zugewiesen werden soll
balise
<html:select name="dynaFormulaire" property="combo">....</html:select>
traduction HTML
<select name="combo">...</select>
explication
Das HTML-Element „html:select“ dient dazu, das Element „HTML <select>...</select>“ zu generieren. Es unterstützt verschiedene Attribute:
name
optional – Name des Beans ActionForm oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, die dem Eingabefeld zum Lesen und Schreiben zugeordnet ist.
value
optional – Wert, der dem Feld HTML zugewiesen werden soll. Die Option der Kombinationsliste mit diesem Wert wird ausgewählt.
balise
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
traduction HTML
<option value="combo1">combo1</option>
<option value="combo2">combo2</option>

explication
Das HTML-Tag „options“ dient dazu, die Tags HTML <option>...</option> innerhalb eines Tags HTML <select> zu generieren. Es gibt verschiedene Möglichkeiten, anzugeben, wie die Ausfüllwerte für das Select-Element ermittelt werden sollen. Hier haben wir die Attribute „name“ und „property“ verwendet:
name
optional – Name des Beans ActionForm oder eines abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes im Formular-Bean, das die Werte des Select-Elements enthält. Es muss sich um ein Array von Zeichenketten handeln.

Die beiden anderen Listen werden analog zur vorherigen generiert:

          <html:select name="dynaFormulaire" property="listeSimple" size="3">
            <html:options name="dynaFormulaire" property="valeursListeSimple"/>            
        </html:select>

Oben wird ein „size“-Attribut ungleich 1 angegeben, um eine Liste anstelle eines Kombinationsfelds zu erhalten.

<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
        <html:options name="dynaFormulaire" property="valeursListeMultiple"/>                
    </html:select>

Oben wird das Attribut „multiple=“true““ festgelegt, um eine Liste mit Mehrfachauswahl zu erhalten.

balise
<html:hidden name="dynaFormulaire" property="secret"/>
traduction HTML
<input type="hidden" name="secret" value="xxx">
explication
Das HTML-Tag „html:hidden“ dient dazu, das Tag „HTML <input type="hidden" ...>“ zu generieren.
name
optional – Name des Beans „ActionForm“ oder eines davon abgeleiteten Beans, in das der Wert des Feldes geschrieben oder aus dem er gelesen werden soll. Fehlt dieses Attribut, wird das mit dem Tag <html:form> verknüpfte Formular verwendet.
property
Name des Feldes in der Formular-Bean, die dem versteckten Feld zugeordnet ist. Der dem geheimen Feld HTML zugewiesene Wert „xxx“ stammt aus der Definition des Formulars in der Konfigurationsdatei. Dort wurde für das geheime Feld ein Anfangswert „xxx“ festgelegt.

Um den Zusammenhang zwischen der Ansicht formulaire.jsp und der Bean dynaFormulaire, die sie im Speicher repräsentiert, richtig zu verstehen, muss man bedenken, dass die Bean dynaFormulaire sowohl zum Lesen als auch zum Schreiben verwendet wird:

Die Anfrage erfolgt, wenn der Benutzer auf die Schaltfläche [Envoyer] im Formular klickt. Der Browser „sendet“ dann das Formular HTML an die Aktion /confirmation. Wir haben bereits erläutert, was dann geschieht, und insbesondere, dass die Felder von dynaFormulaire die Werte der gleichnamigen Felder des Formulars HTML erhalten.

Was geschieht, wenn der Controller als Antwort auf eine Anfrage die Anzeige der Ansicht formulaire.jsp anfordert? Betrachten wir die Tags noch einmal einzeln:

balise
<body background="<html:rewrite page="/images/standard.jpg"/>">
fonction
erzeugt den Code HTML
<body background="/formulaire2/images/standard.jpg">
balise
<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
</html:form>
fonction
erzeugt den Code HTML
<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">
balise
<html:radio name="dynaFormulaire" property="opt" value="ja">Ja</html:radio>
<html:radio name="dynaFormulaire" property="opt" value="nein">Nein</html:radio>
fonction
Wenn das Feld „opt“ von dynaFormulaire den Wert „ja“ hat, generiere den Code HTML
<input type="radio" name="opt" value="oui" checked="checked">Oui
<input type="radio" name="opt" value="non">Non
balise
<html:checkbox name="dynaFormulaire" property="chk1">1</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk2">2</html:checkbox>
<html:checkbox name="dynaFormulaire" property="chk3">3</html:checkbox>
fonction
Wenn die Felder chk1 und chk3 von dynaFormulaire den Wert „on“ haben und das Feld chk2 den Wert „off“ hat, generiere den Code HTML
<input type="checkbox" name="chk1" value="on" checked="checked">1
<input type="checkbox" name="chk2" value="on">2
<input type="checkbox" name="chk3" value="on" checked="checked">3                                                
balise
<html:text name="dynaFormulaire" property="champSaisie" />
fonction
Wenn das Feld champSaisie den Wert „Dies ist ein Test“ hat, wird der Code HTML generiert
<input type="text" name="champSaisie" value="ceci est un essai">
balise
<html:password name="dynaFormulaire" property="mdp" />
fonction
Wenn das Feld „mdp“ den Wert „azerty“ hat, wird der Code HTML generiert
<input type="password" name="mdp" value="azerty">
balise
<html:password name="dynaFormulaire" property="mdp" />
fonction
Wenn das Feld „mdp“ den Wert „azerty“ hat, wird der Code HTML generiert
<input type="password" name="mdp" value="azerty">
balise
<html:password name="dynaFormulaire" property="mdp" />
fonction
Wenn das Feld „mdp“ den Wert „azerty“ hat, wird der Code HTML generiert
<input type="password" name="mdp" value="azerty">
balise
<html:select name="dynaFormulaire" property="combo">
<html:options name="dynaFormulaire" property="valeursCombo"/>
</html:select>
fonction
Wenn das Kombinationsfeld den Wert „combo2“ hat, wird der Code HTML generiert
<select name="combo">
    <option value="combo0">combo0</option>
    <option value="combo1">combo1</option>
    <option value="combo2" selected="selected">combo2</option>
    <option value="combo3">combo3</option>
    <option value="combo4">combo4</option>
</select>
balise
<html:select name="dynaFormulaire" property="listeSimple" size="3">
<html:options name="dynaFormulaire" property="valeursListeSimple"/>
</html:select>
fonction
Wenn das Feld listeSimple den Wert „simple1“ hat, wird der Code HTML generiert
<select name="listeSimple" size="3">
    <option value="simple0">simple0</option>
    <option value="simple1" selected="selected">simple1</option>
    <option value="simple2">simple2</option>
...
</select>
balise
<html:select name="dynaFormulaire" property="listeMultiple" size="5" multiple="true">
<html:options name="dynaFormulaire" property="valeursListeMultiple"/>
</html:select>
fonction
Wenn das Feld listeMultiple das Array {"multiple0", "multiple2"} ist, wird der Code HTML generiert
<select name="listeMultiple" multiple="multiple" size="5">
    <option value="multiple0" selected="selected">multiple0</option>
    <option value="multiple1">multiple1</option>
    <option value="multiple2" selected="selected">multiple2</option>
    <option value="multiple3">multiple3</option>
...
</select>
balise
<html:hidden name="dynaFormulaire" property="secret"/>
fonction
Wenn das Feld „secret“ den Wert „xxx“ hat, wird der Code HTML generiert
<input type="hidden" name="secret" value="xxx">
balise
<html:submit>Senden</html:submit>
fonction
erzeugt den Code HTML
<input type="submit" value="Envoyer">

Als Letztes soll der JavaScript-Code erläutert werden, der in der Seite JSP enthalten ist und mit den beiden Schaltflächen [Effacer] verknüpft ist, die die in den Listen listeSimple und listeMultiple ausgewählten Elemente abwählen:

<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>                                
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>

Das Tag

<html:form action="/confirmation" name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">

erzeugt den folgenden Code HTML:

<form name="dynaFormulaire" method="post" action="/formulaire2/confirmation.do">

Um den JavaScript-Code zu verstehen, der mit den Schaltflächen [Effacer] verbunden ist, wollen wir uns noch einmal vor Augen führen, wie die verschiedenen Elemente eines Webdokuments in einem JavaScript-Code bezeichnet werden, der dieses Dokument nutzt:

Bezeichnung
Bedeutung
document
bezeichnet das gesamte Webdokument
document.forms
bezeichnet die Sammlung der im Dokument definierten Formulare
document.forms[i]
bezeichnet das Formular Nr. i des Dokuments
document.forms["nomFormulaire"]
bezeichnet das Formular <form>, dessen Attribut „name“ den Wert „nomFormulaire“ hat
document.nomFormulaire
bezeichnet das Formular <form>, dessen Attribut „name“ den Wert „nomFormulaire“ hat
document.[formulaire].elements
bezeichnet die Sammlung der Elemente, die zu dem durch den Ausdruck [formulaire] bezeichneten Formular gehören. Diese Sammlung umfasst alle Tags <input>, <textarea> und <select> des bezeichneten Formulars.
document.[formulaire].elements[i]
bezeichnet das Element Nr. i von [formulaire]
document.[formulaire].elements["nomComposant"]
bezeichnet das Element von [formulaire], dessen Attribut „name“ den Wert nomComposant hat
document.[formulaire]. nomComposant
bezeichnet das Element von [formulaire], dessen Attribut „name“ den Wert „nomComposant“ hat
document.[formulaire].[composant].value
bezeichnet den Wert der Komponente [composant] des Formulars [formulaire], wenn der Code HTML dieses Formulars ein „value“-Attribut haben kann (<input>, <textarea>)
document.[formulaire].[select].selectedIndex
bezeichnet den Index der in einer Liste ausgewählten Option. Kann zum Lesen und Schreiben verwendet werden. Wenn diese Eigenschaft auf -1 gesetzt wird, werden alle Elemente der Liste abgewählt.
document.[formulaire].[select].options
bezeichnet das Array der Optionen, die einem <select>-Tag zugeordnet sind
document.[formulaire].[select].options[i]
bezeichnet die Option Nr. i des angegebenen <select>-Tags
document.[formulaire].[select].options[i].selected
Boolescher Wert, der angibt, ob die Option Nr. i des angegebenen Tags [select] ausgewählt ist (true) oder nicht. Kann zum Lesen und Schreiben verwendet werden

Werfen wir noch einmal einen Blick auf den JavaScript-Code der beiden Schaltflächen:

<input type="button" value="Effacer" onclick="this.form.listeSimple.selectedIndex=-1"/>                                
<input type="button" value="Effacer" onclick="this.form.listeMultiple.selectedIndex=-1"/>

Beim Klicken auf die Schaltfläche wird der dem Attribut „onclick“ zugeordnete Code ausgeführt. Hier handelt es sich um Inline-Code. Meistens schreibt man onclick="Funktion(...)", wobei „Funktion“ eine Funktion ist, die innerhalb eines Tags <script language="javascript">...</script> definiert ist. Was macht der obige Code? Kommentieren wir den Code der ersten Schaltfläche:

this
bezeichnet das Webdokument, in dem sich die Schaltfläche befindet
this.form
bezeichnet das Formular, in dem sich die Schaltfläche befindet
this.form.listeSimple
bezeichnet die Komponente listeSimple des Formulars
this.form.listeSimple.selectedIndex
bezeichnet den Index der in listeSimple ausgewählten Option. Wenn Sie diese Eigenschaft auf -1 setzen, wird die Auswahl aller Optionen aufgehoben.

6.4.2. Die Ansicht confirmation.jsp

Zur Erinnerung: Diese Ansicht wird nach Abschluss der Aktion /Bestätigung c.a.d angezeigt, nachdem das in der Ansicht formulaire.jsp enthaltene Formular vom Web-Client übermittelt wurde. Ihr einziger Zweck besteht darin, die vom Benutzer eingegebenen Werte anzuzeigen. Ihr Code lautet wie folgt:

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

<html>
    <head>
      <title>Confirmation</title>
  </head>
  <body background="<html:rewrite page="/images/standard.jpg"/>">
      <h3>Confirmation des valeurs saisies</h3>
    <hr/>
    <table border="1">
        <tr>
        <td>Bouton radio</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="opt"/></td>
      </tr>
        <tr>
        <td>Case à cocher chk1</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="chk1"/></td>
      </tr>
        <tr>
        <td>Case à cocher chk2</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="chk2"/></td>
      </tr>
        <tr>
        <td>Case à cocher chk3</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="chk3"/></td>
      </tr>

        <tr>
        <td>Champ de saisie</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="champSaisie"/></td>
      </tr>
        <tr>
        <td>Mot de passe</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="mdp"/></td>
      </tr>

        <tr>
        <td>Boîte de saisie</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="boiteSaisie"/></td>
      </tr>

        <tr>
        <td>combo</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="combo"/></td>
      </tr>
        <tr>
        <td>liste simple</td>
        <td><bean:write name="dynaFormulaire" scope="session" property="listeSimple"/></td>
      </tr>
            <logic:iterate id="choix" indexId="index" name="dynaFormulaire" property="listeMultiple">
          <tr>
          <td>liste multiple[<bean:write name="index"/>]</td>
          <td><bean:write name="choix"/></td>
        </tr>
            </logic:iterate>
    </table>
        <br>
    <html:link page="/affiche.do">
            Retour au formulaire
        </html:link>    
  </body>
</html>

Wir stellen hier zwei neue Tag-Bibliotheken vor: struts-bean und struts-logic. Die Bibliothek struts-bean ermöglicht den Zugriff auf Objekte, die in der Anfrage, der Sitzung oder dem Anwendungskontext abgelegt sind. Die Bibliothek „struts-logic“ ermöglicht es, mithilfe von Tags Ausführungslogik einzubinden. Diese beiden Bibliotheken sind keineswegs unverzichtbar. Wie wir gesehen haben, kann eine Seite JSP:

  • Objekte aus der Anfrage (request.getAttribute(...)), der Sitzung (session.getAttribute(...)) oder dem Anwendungskontext abrufen
  • dynamische Teile mithilfe von Variablen <%= Variable %> in den Code HTML einbinden
  • Java-Code enthalten <% Java-Code %>

Das Einfügen von Java-Code in JSP-Seiten stört alle, die eine strikte Trennung zwischen Anwendungslogik (Java-Code) und Darstellung (Verwendung von Tags) wünschen. Deshalb wurden für sie Tag-Bibliotheken entwickelt.

Wir gehen genauso vor wie bei der Ansicht formulaire.jsp und erläutern jedes der im Code von confirmation.jsp vorhandenen Tags, sofern diese nicht bereits in der Ansicht formulaire.jsp behandelt wurden. Zunächst ist zu beachten, dass die Seite mit der Deklaration der drei Tag-Bibliotheken beginnt, die sie verwenden wird:

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>

Beachten Sie außerdem, dass diese drei Bibliotheken in der Datei web.xml der Anwendung deklariert werden müssen. Wir kommentieren nun die Tags des Dokuments formulaire.jsp:

balise
<bean:write name="dynaFormulaire" scope="session" property="opt"/>
fonction
schreibt einen Wert in den aktuellen Datenstrom HTML. Das Tag „bean:write“ unterstützt die folgenden Attribute:
name: Name des zu verwendenden Objekts
scope: Geltungsbereich (request, session, context), in dem nach diesem Objekt gesucht werden soll
property: Feld des durch „name“ bezeichneten Objekts, dessen Eigenschaft geschrieben werden soll. Dieses Feld kann ein Objekt beliebigen Typs sein. Es wird die Methode toString des Objekts verwendet.
Hier wird der Wert des Felds „opt“ von dynaFormulaire geschrieben. Der Wert lautet entweder „ja“, wenn der Benutzer das Optionsfeld mit dem Attribut „value=“ja““ ausgewählt hat, oder „nein“, wenn er das Optionsfeld mit dem Attribut „value=“nein““ ausgewählt hat
balise
<bean:write name="dynaFormulaire" scope="session" property="chk1"/>
fonction
Schreibt den Wert des Feldes chk1 aus dynaFormulaire. Der Wert ist entweder „on“, wenn der Benutzer das Kontrollkästchen aktiviert hat, oder „off“, wenn nicht. Gleiches gilt für chk2 und chk3.
balise
<bean:write name="dynaFormulaire" scope="session" property="champSaisie"/>
fonction
schreibt den Wert des Feldes champSaisie aus dynaFormulaire, d. h. den vom Benutzer in dieses Feld eingegebenen Text. Gleiches gilt für „mdp“, boiteSaisie.
balise
<bean:write name="dynaFormulaire" scope="session" property="combo"/>
fonction
schreibt den Wert des Kombinationsfelds von dynaFormulaire. Man erhält das Attribut „value“ des vom Benutzer ausgewählten Elements <option>.
balise
<bean:write name="dynaFormulaire" scope="session" property="listeSimple"/>
fonction
Schreibt den Wert des Feldes listeSimple aus dynaFormulaire. Dabei wird das Attribut „value“ des vom Benutzer ausgewählten Elements <option> verwendet, sofern ein solches vorhanden war. Andernfalls wird die leere Zeichenfolge zurückgegeben.
balise
            <logic:iterate id="choix" indexId="index" name="dynaFormulaire" property="listeMultiple">
          <tr>
          <td>liste multiple[<bean:write name="index"/>]</td>
          <td><bean:write name="choix"/></td>
        </tr>
            </logic:iterate>
fonction
Hier fügen wir Logik-Tags ein. Es handelt sich um eine Auswahlliste. Der Wert des Feldes listeMultiple des Objekts dynaFormulaire ist ein String-Array. In Java würden wir eine Schleife schreiben. Mit dem Tag „logic:iterate“ können wir dieselbe Schleife ausführen, ohne Java-Code schreiben zu müssen. Das Tag „logic:iterate“ hat im Beispiel die folgenden Attribute:
name="dynaFormulaire": Name des zu verwendenden Objekts
property="listeMultiple": Name der Eigenschaft, die in dem durch „name“ angegebenen Objekt die Sammlung enthält, die in der Schleife durchlaufen wird. Hier ist diese Sammlung das Array der in listeMultiple ausgewählten Werte. Dieses Array kann leer sein.
id="choix": Kennung, die bei jedem Durchlauf der Schleife das aktuelle Element des Arrays bezeichnet. Bei der ersten Iteration steht „choix“ für listeMultiple[0], bei der zweiten für listeMultiple[1] und so weiter.
indexID="index": Bezeichner, der bei jedem Durchlauf der Schleife den Index des aktuellen Elements des Arrays angibt. Bei der ersten Iteration hat „index“ den Wert 0, bei der zweiten den Wert 1 und so weiter.
Der Code HTML, der zwischen den Tags <logic:iterate ...> und </logic:iterate> steht, wird für jedes Element der durch das Paar (name,property) bezeichneten Sammlung wiederholt. Der dynamische Teil dieses Codes lautet wie folgt:
          <td>liste multiple[<bean:write name="index"/>]</td>
          <td><bean:write name="choix"/></td>
Aus den vorangegangenen Ausführungen folgt, dass bei der Iteration Nr. i (i >= 0) der generierte Code HTML dem folgenden Code entspricht:
          <td>liste multiple[<%=i%>]</td>
          <td><%=listeMultiple[i]%></td>
balise
    <html:link page="/affiche.do">
            Retour au formulaire
        </html:link>    
fonction
erzeugt einen Link, der sich auf den Kontext der Anwendung bezieht, sodass dessen Kenntnis nicht erforderlich ist. Der durch dieses Tag generierte Code HTML lautet wie folgt:
<a href="/formulaire2/affiche.do">Retour au formulaire</a>

6.5. Die Java-Klassen

Die Konfigurationsdatei struts-config.xml verweist auf zwei Java-Klassen:

        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
...
      <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >

Die Klasse DynaFormulaire ist die Klasse, die die Werte der Ansicht Nr. 1 formulaire.jsp enthält. Die Klasse InitFormulaireAction ist die Klasse, die die Werte des Formulars verarbeitet, das über die Schaltfläche [Envoyer] von formulaire.jsp übermittelt wurde.

6.5.1. Die Klasse DynaFormulaire

Um die Werte eines Formulars zu speichern, reicht ein Objekt vom Typ DynaActionForm aus, es sei denn, eine der Methoden „reset“ oder „validate“ dieser Klasse muss neu definiert werden. In diesem Fall muss die Methode „validate“ nicht neu definiert werden, da keine Datenvalidierung durchgeführt wird. Die Methode „reset“ muss jedoch neu definiert werden. Denn die Felder des Objekts DynaFormulaire erhalten ihre Werte aus dem vom Web-Client gesendeten Formular. Bestimmte Felder erhalten jedoch möglicherweise keinen Wert, wenn sie in der Anfrage nicht vorhanden sind. Dies tritt in den folgenden Fällen auf:

  • ein Kontrollkästchen, das vom Benutzer nicht angekreuzt wurde
  • eine Liste mit mehr als einem Eintrag oder es wurde keine Option ausgewählt

Bei Formularen mit dieser Art von Komponente muss die Methode „reset“

  • dem Feld, das dem Kontrollkästchen zugeordnet ist, den Wert „off“ zuweisen
  • dem Feld, das einer Liste mit Einzelauswahl zugeordnet ist, die leere Zeichenkette zuweisen
  • dem Feld, das einer Mehrfachauswahlliste zugeordnet ist, ein Array von Zeichenfolgen der Größe Null zuweisen

Wenn diese Felder also keinen Wert aus der Abfrage erhalten, behalten sie den durch „reset“ zugewiesenen Wert bei, der dem Zustand der Komponente in dem vom Benutzer validierten Formular entspricht (Kontrollkästchen nicht markiert, Liste ohne ausgewähltes Element).

Der Code der Klasse DynaFormulaire, einer von DynaActionForm abgeleiteten Klasse, lautet wie folgt:

package istia.st.struts.formulaire;

import org.apache.struts.action.DynaActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;

public class DynaFormulaire extends DynaActionForm {
  public void reset(ActionMapping mapping, HttpServletRequest request){
    // Checkboxen zurücksetzen – Wert „off“
    set("chk1","off");
    set("chk2","off");
    set("chk2","off");
    // Zurücksetzen von listeSimple – leere Zeichenfolge
    set("listeSimple","");
     // Zurücksetzen von listeMultiple – leeres Array
    set("listeMultiple",new String[]{});
  }
}

6.5.2. Die Klasse InitFormulaireAction

Die Klasse InitFormulaireAction ist in der Datei struts-config.xml der Aktion /init zugeordnet:

      <action
          path="/init"
            name="dynaFormulaire"
            validate="false" 
            scope="session"
          type="istia.st.struts.formulaire.InitFormulaireAction"
      >
            <forward name="afficherFormulaire" path="/vues/formulaire.jsp"/>
        </action>

Die Aktion /init wird nur einmal beim anfänglichen Aufbau des Objekts DynaFormulaire verwendet. Sie dient dazu, die drei Listen des Kombinationsfelds listeSimple, listeMultiple mit Inhalten zu füllen. Dieser Inhalt wird in Form von drei Arrays bereitgestellt, die Eigenschaften des Objekts dynaFormulaire sind:

        <form-bean name="dynaFormulaire" type="istia.st.struts.formulaire.DynaFormulaire">
            <form-property name="opt" type="java.lang.String" initial="non"/>
...
            <form-property name="valeursCombo" type="java.lang.String[]" />
            <form-property name="valeursListeSimple" type="java.lang.String[]" />
            <form-property name="valeursListeMultiple" type="java.lang.String[]"/>                                          
        </form-bean>            

Sobald die Tabellen valeursCombo, valeursListeSimple und valeursListeMultiple durch InitFormulaireAction initialisiert wurden, müssen sie nicht erneut initialisiert werden. Das Objekt dynaFormulaire wird nämlich in die Sitzung aufgenommen und behält daher seinen Wert über mehrere Anfrage-Antwort-Zyklen hinweg bei. Aus diesem Grund wird die Aktion /init nur einmal ausgeführt. Der Code von InitFormulaireAction lautet wie folgt:

package istia.st.struts.formulaire;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class InitFormulaireAction
  extends Action {
  public ActionForward execute(ActionMapping mapping, ActionForm form,
       HttpServletRequest request, HttpServletResponse response) throws IOException,    ServletException {

     // bereitet das Formular zur Anzeige vor

     // Die erforderlichen Informationen werden in die Bean des Formulars geschrieben
    DynaFormulaire formulaire = (DynaFormulaire) form;
    formulaire.set("valeursCombo", getValeurs(5, "combo"));
    formulaire.set("valeursListeSimple", getValeurs(7, "simple"));
    formulaire.set("valeursListeMultiple", getValeurs(10, "multiple"));
     // die Kontrolle wird zurückgegeben
    return mapping.findForward("afficherFormulaire");
  } //wird ausgeführt

   // Liste der Werte des Kombinationsfelds
  private String[] getValeurs(int taille, String label) {
    String[] valeurs = new String[taille];
    for (int i = 0; i < taille; i++) {
      valeurs[i] = label + i;
    }
    return valeurs;
  }
}
  • Die Klasse leitet sich von der Klasse „Action“ ab. Dies ist zwingend erforderlich.
  • Der Struts-Controller verwendet über seine Methode „execute“ ein Action-Objekt. Diese Methode muss daher neu definiert werden. Sie erhält die folgenden Parameter:
    • ActionMapping mapping: ein Objekt, das die Konfiguration der Anwendung in struts-config.xml darstellt
    • ActionForm form: das der Aktion zugeordnete Formular, sofern in der Konfiguration der Aktion eines definiert ist (Attribut „name“ der Aktion).
    • HttpServletRequest request: die Anfrage des Clients
    • HttpServletResponse: die Antwort an den Client
  • Die Klasse InitFormulaireAction muss das Formular dynaFormulaire initialisieren. Dieses wird in der Methode „execute“ als Parameter ActionForm form übergeben. Zur Erinnerung: dynaFormulaire ist vom Typ DynaFormulaire, einer Klasse, die von der Klasse DynaActionForm abgeleitet ist, die wiederum von der Klasse ActionForm abgeleitet ist.
  • In der Methode „execute“ werden den drei Feldern valeursCombo, valeursListeSimple und valeursListeMultiple mithilfe der Methode „set“ der Klasse DynaActionForm Werte zugewiesen. Der Einfachheit halber handelt es sich bei diesen Werten um beliebige Arrays. Beachten Sie, dass die Methode „set“ einem vorhandenen Feld einen Wert zuweist. Sie kann nicht zum Anlegen neuer Felder verwendet werden. Aus diesem Grund müssen die drei Felder valeursCombo, valeursListeSimple, valeursListeMultiple in der Definition des Objekts dynaFormulaire in struts-config.xml zu definieren.
  • Die Methode „execute“ endet damit, dass sie dem Controller den Schlüssel der anzuzeigenden Ansicht als Antwort an den Client zurückgibt. In diesem Fall ist es der Schlüssel afficherFormulaire, der in der Datei struts-config.xml der Ansicht /vues/formulaire.jsp zugeordnet wurde.

6.6. Bereitstellung

Die Verzeichnisstruktur der Anwendung sieht wie folgt aus:

  

Image

Image

Zur Erinnerung: Die oben genannte Datei „ApplicationResources.properties“ wird von der Struts-Bean-Tag-Bibliothek benötigt. Diese Datei enthält die Meldungen der Anwendung, auf die die Struts-Bean-Bibliothek zugreifen kann. In unserer Anwendung sind jedoch keine Meldungen definiert. Daher existiert die Datei „ApplicationResources.properties“ zwar, ist aber leer.

6.7. Fazit

In dieser Lektion haben wir detailliert beschrieben, wie die verschiedenen Komponenten eines Formulars HTML verwaltet werden. Wir können nun komplexe Formulare in unseren Struts-Anwendungen verwenden.