4. Verwendung dynamischer Formulare
4.1. Deklaration des dynamischen Formulars
Wir haben gesehen, dass Struts ActionForm-Objekte verwendet, um die Werte von HTML-Formularen zu speichern, die von den verschiedenen Servlets der Anwendung verarbeitet werden. Für jedes Formular in unserer Anwendung müssen wir eine von ActionForm abgeleitete Klasse erstellen. Dies kann schnell mühsam werden, da wir für jedes Feld xx zwei Methoden schreiben müssen: setXx und getXx. Struts bietet die Möglichkeit, Formulare zu verwenden
- , deren Struktur in der Datei struts-config.xml innerhalb des Abschnitts <form-beans>
- , die von der Struts-Umgebung entsprechend der deklarierten Struktur dynamisch erstellt werden
Somit könnte die Klasse, die in der Anwendung strutspersonne zum Speichern der Werte für Name und Alter verwendet wird, wie folgt definiert werden:
<form-beans>
<form-bean name="frmPersonne" type="org.apache.struts.actions.DynaActionForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
Für jedes Feld im Formular definieren wir ein <form-property>-Tag mit zwei Attributen:
- name: der Feldname
- type: sein Java-Typ
Da die Werte eines von einem Web-Client gesendeten Formulars Zeichenfolgen sind, sind die am häufigsten verwendeten Typen java.lang.String für Felder mit einem einzigen Wert und java.lang.String[] für Felder mit mehreren Werten (Kontrollkästchen mit demselben Namen, Mehrfachauswahllisten usw.). Die Klasse DynactionForm verfügt, wie die Klasse ActionForm, über eine validate-Methode, die nichts tut. Damit sie die Gültigkeit der Formularparameter überprüft, müssen Sie sie erweitern und die validate-Methode selbst schreiben. Die Formulardeklaration sieht daher wie folgt aus:
<form-beans>
<form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
Wir müssen die Klasse **istia.st.struts.personne.PersonneDynaForm** selbst schreiben.
4.2. Erstellen der mit dem dynamischen Formular verbundenen DynaActionForm-Klasse
Oben haben wir die Klasse „istia.st.struts.personne.PersonneDynaForm“ dem Formular (Name, Alter) zugeordnet. Wir werden nun diese Klasse schreiben:
package istia.st.struts.personne;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class PersonneDynaForm extends DynaActionForm {
// validation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// error management
ActionErrors erreurs = new ActionErrors();
// name must be non-empty
String nom = (String)this.get("nom");
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
}
// age must be non-empty
String age = (String)this.get("age");
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// age must be a positive integer
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// return the list of errors
}
} //if
// return the error list
return erreurs;
}
}//class
Folgende Punkte sind zu beachten:
- Die Klasse leitet sich von DynaActionForm ab
- Die validate-Methode der DynaActionForm-Klasse wurde umgeschrieben. Wenn sie vom Struts-Controller ausgeführt wird, wird das PersonneDynaForm-Objekt instanziiert. Es enthält ein Dictionary, dessen Schlüssel die Formularfelder name und age sind und dessen Werte die Werte dieser Felder sind. Um innerhalb von DynaActionForm-Methoden auf ein Feld zuzugreifen, verwenden Sie die Methode Object get(String fieldName). Um einen Wert für ein Feld festzulegen, verwenden Sie die Methode void set(String fieldName, Object value). Eine vollständige Beschreibung finden Sie in der Klassendefinition von DynaActionForm.
- Sobald die Werte der Formularfelder „name“ und „age“ abgerufen wurden, unterscheidet sich die validate-Methode nicht mehr von derjenigen, die geschrieben wurde, als das Formular mit einem ActionForm-Objekt verknüpft wurde.
4.3. Die neue FormAction-Klasse
Die Konfigurationsdatei definiert die folgende /main-Aktion:
...
<form-beans>
<form-bean name="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
....
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
Diese Definition entspricht der in der Anwendung strutspersonne. Die Aktion /main wird durch ein Objekt vom Typ FormulaireAction implementiert. Dieses Objekt empfing früher die Werte aus dem Formular frmPersonne in einem Objekt vom Typ FormulaireBean. Nun empfängt es sie in einem Objekt vom Typ PersonneDynaForm. Daher muss die Klasse umgeschrieben werden:
package istia.st.struts.personne;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
import istia.st.struts.personne.PersonneDynaForm;
public class FormulaireAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
// we have a valid form, otherwise we wouldn't have got here
PersonneDynaForm formulaire=(PersonneDynaForm)form;
request.setAttribute("nom",formulaire.get("nom"));
request.setAttribute("age",formulaire.get("age"));
return mapping.findForward("reponse");
}//execute
}
Folgende Punkte sind zu beachten:
- Wir müssen die Klasse PersonneDynaForm importieren, die die Formulardaten enthält, um auf ihre Definition zugreifen zu können
- Die Methode `execute` ruft die Werte der Formularparameter mithilfe der Methode `[DynaActionForm].get` ab.
Im Vergleich zur FormAction-Klasse in der Anwendung strutspersonne hat sich lediglich die Art und Weise geändert, wie auf die Formularwerte zugegriffen wird.
4.4. Bereitstellung und Testen der Anwendung „strutspersonne1“
4.4.1. Erstellen des Kontexts
Wir haben diese neue Anwendung strutspersonne1 genannt. Wir erstellen eine neue Definition in der Datei <tomcat>\conf\serveur.xml für Tomcat 4.x:
Anschließend muss Tomcat neu gestartet werden. Sie können die Gültigkeit des Kontexts überprüfen, indem Sie die URL aufrufen:
http://localhost:8080/strutspersonne1/

4.4.2. Die Ansichten
Kopieren Sie den Ordner „views“ aus der Anwendung „strutspersonne“ in den Ordner der Anwendung „strutspersonne1“. Die Ansichten haben sich nicht geändert.

4.4.3. Kompilieren der Klassen
Wir müssen zwei Klassen erstellen: „PersonneDynaForm“ und „FormulaireAction“, wobei letztere die erstere verwendet. Wir können sie mithilfe eines JBuilder-Projekts erstellen und kompilieren:

4.4.4. Der Ordner WEB-INF
Kopieren Sie den Ordner „WEB-INF“ aus der Anwendung „strutspersonne“ in den Ordner der Anwendung „strutspersonne1“. Einige Dateien haben sich geändert:

Die Konfigurationsdatei struts-config.xml sieht nun 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="frmPersonne" type="istia.st.struts.personne.PersonneDynaForm">
<form-property name="nom" type="java.lang.String" initial=""/>
<form-property name="age" type="java.lang.String" initial=""/>
</form-bean>
</form-beans>
<action-mappings>
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
<action
path="/erreurs"
parameter="/vues/erreurs.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/reponse"
parameter="/vues/reponse.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
<message-resources parameter="ressources.personneressources"/>
</struts-config>
Diese Datei ist identisch mit der der Anwendung „strutspersonne“, mit Ausnahme der Definition des dynamischen Formulars (eingerahmter Abschnitt).
Legen Sie die von JBuilder kompilierten Klassen im Ordner WEB-INF/classes ab:

Legen Sie die Meldungsdatei im Ordner WEB-INF\classes\resources ab. Sie hat sich nicht geändert.
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.vide=<li>Vous devez indiquer un age</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
errors.header=<ul>
errors.footer=</ul>

4.5. Tests
Wir sind bereit für die Tests. Nachfolgend finden Sie einige Screenshots, die der Leser gerne nachstellen kann.
Rufen Sie die URL http://localhost:8080/strutspersonne1/formulaire.do auf:

Klicken Sie auf die Schaltfläche [Absenden], ohne die Felder auszufüllen:

Versuchen Sie es erneut mit einem Fehler im Feld „Alter“:

Wir erhalten folgende Antwort:

Versuchen Sie es erneut und geben Sie diesmal die richtigen Werte ein:

Wir erhalten folgende Antwort:

4.6. Fazit
Die Verwendung dynamischer Formulare erleichtert das Schreiben von ActionForm-Klassen, die für die Speicherung von Formularwerten zuständig sind. Wir können die Formularverwaltung noch einen Schritt weiterführen. In der Anwendung strutspersonne1 haben wir eine PersonneDynaForm-Klasse erstellt, um die Werte des Formulars (Name, Alter) zu validieren. In der Praxis kommen bestimmte Validierungen häufig vor: nicht leeres Feld, Feld, das einen bestimmten regulären Ausdruck validiert, Ganzzahlfeld, Datumsfeld usw. Diese Art der Standardvalidierung kann dann in der Konfigurationsdatei struts-config.html festgelegt werden. Wenn alle durchzuführenden Validierungen „Standard“ sind, besteht keine Notwendigkeit, eine Klasse für das Formular zu schreiben. Dies werden wir nun untersuchen.