11. Beispiel 09 – Konvertierung und Validierung von Ganzzahlen
Wir werden uns nun eine Reihe von Beispielen zur Konvertierung und Validierung von Formularparametern ansehen. Das Problem stellt sich wie folgt dar: Um eine URL der Form [http://machine:port/.../Action] zu verarbeiten, instanziiert der [FilterDispatcher]-Controller die Klasse, die die angeforderte Aktion implementiert, und führt eine ihrer Methoden aus – standardmäßig die Methode namens execute. Der Aufruf dieser execute-Methode durchläuft eine Reihe von Interceptors:
![]() |
Die Liste der Interceptors ist in der Datei [struts-default.xml] im Stammverzeichnis des Archivs [struts2-core.jar] definiert. Die dort definierte Liste der Interceptors lautet wie folgt:
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
Unter den Interceptors gibt es einen, der dafür zuständig ist, die Werte der mit der Anfrage übermittelten Parameter in Form von „parami=values“ in die Aktion einzufügen. Wir wissen, dass die Werte über die Methode „setParami“ in das Feld „parami“ der Aktion eingefügt werden, sofern dieses vorhanden ist. Andernfalls erfolgt keine Einfügung und es wird kein Fehler gemeldet.
Die Zeichenfolge parami=values ist eine Zeichenkette. Bislang erfolgte die Einfügung von Werten in parami-Felder vom Typ String:
Das Einfügen der Zeichenkette „valeuri“ als Wert der Zeichenkette „parami“ stellte kein Problem dar. Ist „parami“ nicht vom Typ String, muss „valeuri“ in den Typ „Ti“ von „parami“ konvertiert werden. Dies ist das Konvertierungsproblem. Beispielsweise möchten wir vielleicht, dass ein Alter eine Ganzzahl ist, und schreiben in der Aktion:
Außerdem möchten wir das Alter vielleicht auf den Bereich zwischen 1 und 150 beschränken. Dies wirft ein Validierungsproblem auf. Der Parameter parami kann in den richtigen Typ konvertiert werden, ohne dass er zwangsläufig gültig ist. Es sind daher zwei Schritte erforderlich. Zurück zum Diagramm der Anforderungsverarbeitung:
![]() |
Zwei Interceptors übernehmen jeweils die Konvertierung und die Validierung der Parameter. Wenn einer der beiden Schritte fehlschlägt, wird die Anfrage nicht an die Aktion weitergeleitet (roter Pfad oben). Das Formular, über das die fehlerhaften Parameter übermittelt wurden, wird mit Fehlermeldungen erneut angezeigt.
Die an der Parameterkonvertierung und -validierung beteiligten Interceptors sind die Interceptors „conversionError“ und „validation“ in den Zeilen 19 und 20 der zuvor gezeigten Interceptor-Liste. Beachten Sie in den Zeilen 20–22, dass der Validierungs-Interceptor nicht angewendet wird, wenn es sich bei der aufgerufenen Methode um eine der Methoden „input“, „back“, „cancel“ oder „browse“ handelt. Wir werden diese Eigenschaft später nutzen.
Wir beginnen mit der Untersuchung der Konvertierung und Validierung von Ganzzahlen. Wir werden uns etwas Zeit für dieses erste Beispiel nehmen, da die Validierung viele Elemente umfasst. Sobald wir diese verstanden haben, werden wir die folgenden Beispiele zügiger durchgehen.
11.1. Das Formular
![]() |
- in [1], das Eingabeformular
- in [2], das Ergebnis bei der Validierung ohne Eingabe von Werten
11.2. Das NetBeans-Projekt
Das NetBeans-Projekt sieht wie folgt aus:
![]() |
- in [1] die drei Ansichten der Anwendung
- in [2] der Quellcode, die internationalisierten Meldungsdateien und die Struts-Konfigurationsdateien.
11.3. Struts-Konfiguration
Die Anwendung wird über die Dateien [struts.xml] und [example.xml] konfiguriert.
Die Datei [struts.xml] sieht wie folgt aus:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="messages" />
<include file="example/example.xml"/>
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">Accueil</param>
<param name="namespace">/example</param>
</result>
</action>
</package>
</struts>
Die Zeilen 12–18 definieren die Aktion [/example/Home] als Standardaktion, wenn der Benutzer keine angibt.
Die Datei [example.xml] sieht wie folgt aus:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Accueil">
<result name="success">/example/Accueil.jsp</result>
</action>
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
</package>
</struts>
- Zeilen 8–10: Die Aktion [Home] zeigt die Ansicht [Home.jsp] an
- Zeile 11: Die Aktion [FormInt] führt standardmäßig die Methode „execute“ der Klasse [example.FormInt] aus. Wir werden sehen, dass zwei weitere Methoden ausgeführt werden: die Methoden „input“ und „cancel“. Diese Methoden werden dann in den Anfrageparametern angegeben.
- Zeile 12: Der Schlüssel „input“ zeigt die Ansicht [FormInt.jsp] an (Zeile 5). Diese Ansicht ist die Formularansicht.
- Zeile 13: Der Schlüssel „cancel“ wird von einer „cancel“-Methode zurückgegeben, die mit dem Link [Cancel] verknüpft ist. Die gerenderte Ansicht ist dann nach einer Weiterleitung (type=redirect) die Ansicht [Home.jsp].
- Zeile 14: Der Schlüssel `success` wird von der Methode `execute` der Aktion [FormInt] zurückgegeben. Wenn die Anfrage die Methode `execute` erreicht, bedeutet dies, dass sie alle Interceptors erfolgreich durchlaufen hat, insbesondere diejenigen, die die Gültigkeit der Parameter überprüfen. Die Methode `execute` gibt dann einfach den Schlüssel `success` zurück, wodurch die Bestätigungsansicht [ConfirmationInt.jsp] angezeigt wird.
11.4. Meldungsdateien
Die Datei [messages.properties] sieht wie folgt aus:
Accueil.titre=Accueil
Accueil.message=Struts 2 - Conversions et validations
Accueil.FormInt=Saisie de nombres entiers
Form.titre=Conversions et validations
FormInt.message=Struts 2 - Conversion et validation de nombres entiers
Form.submitText=Valider
Form.cancelText=Annuler
Form.clearModel=Raz mod\u00e8le
Confirmation.titre=Confirmation
Confirmation.message=Confirmation des valeurs saisies
Confirmation.champ=champ
Confirmation.valeur=valeur
Confirmation.lien=Formulaire de test
Zusätzlich zu dieser Datei verwenden die Ansichten die folgende [FormInt.properties]-Datei:
int1.prompt=1-Nombre entier positif de deux chiffres
int1.error=Tapez un nombre entier positif de deux chiffres
int2.prompt=2-Nombre entier
int2.error=Tapez un nombre entier
int3.prompt=3-Nombre entier >=-1
int3.error=Tapez un nombre entier >=-1
int4.prompt=4-Nombre entier <=10
int4.error=Tapez un nombre entier <=10
int5.prompt=5-Nombre entier dans l''intervalle [1,10]
int5.error=Tapez un nombre entier dans l''intervalle [1,10]
int6.prompt=6-Nombre entier dans l''intervalle [2,20]
int6.error=Tapez un nombre entier dans l''intervalle [2,20]
Die Datei [FormInt.properties] wird nur verwendet, wenn die Aktion, die die Ansicht generiert hat, die Aktion [FormInt] ist. Dies ist eine Möglichkeit, die Meldungsdatei aufzuteilen, falls sie zu groß wird. Die Meldungen für die Aktion „Action“ sind in der Datei [Action.properties] lokalisiert.
11.5. Ansichten und Aktionen
Wir stellen nun die Ansichten und Aktionen der Anwendung vor. Basierend auf der Anwendungskonfiguration:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Accueil">
<result name="success">/example/Accueil.jsp</result>
</action>
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
</package>
</struts>
Wir sehen, dass es drei Ansichten [Home.jsp, FormInt.jsp, ConfirmationFormInt.jsp] und zwei Aktionen [Home, FormInt] gibt.
11.5.1. Home.jsp
Die Ansicht [Home.jsp] sieht wie folgt aus:

Der Code lautet wie folgt:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Accueil.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Accueil.message"/></h2>
<ul>
<li>
<s:url id="url" action="FormInt!input"/>
<s:a href="%{url}"><s:text name="Accueil.FormInt"/></s:a>
</li>
</ul>
</body>
</html>
Der Link in Zeile 14 erzeugt den folgenden HTML-Code:
<a href="<a href="view-source:http://localhost:8084/exemple-09/example/FormInt.action">/exemple-09/example/FormInt!input.action</a>">Saisie de nombres entiers</a>
Dies ist also ein Link zur Aktion [FormInt], die in [example.xml] wie folgt konfiguriert ist:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
Durch Klicken auf den Link wird die Klasse [example.FormInt] instanziiert und ihre input-Methode ausgeführt. Da diese nicht existiert, wird die input-Methode der übergeordneten Klasse ActionSupport ausgeführt. Diese Methode führt nichts anderes aus, als den input-Schlüssel zurückzugeben. Daher wird die Ansicht [/example/FormInt.jsp] angezeigt.
Darüber hinaus gehört die Eingabemethode zu den Methoden, die vom Validierungs-Interceptor ignoriert werden:
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
Daher findet keine Parametervalidierung statt. Dies ist wichtig, da hier keine Parameter vorhanden sind und wir später sehen werden, dass die Validierungsregeln das Vorhandensein von sechs Parametern erfordern.
11.5.2. Die [FormInt]-Aktion
Die Aktion [FormInt] ist mit der folgenden Klasse [FormInt] verknüpft:
package example;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
public class FormInt extends ActionSupport implements ModelDriven, SessionAware {
// constructor without parameters
public FormInt() {
}
// action model
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
public String cancel() {
// cleaning the model
((FormIntModel) getModel()).clearModel();
// result
return "cancel";
}
@SkipValidation
public String clearModel() {
// close to the model
((FormIntModel) getModel()).clearModel();
// result
return INPUT;
}
// SessionAware
private Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
// validation
@Override
public void validate() {
// valid int6 input?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
}
}
Wir werden diesen Code bei Bedarf kommentieren. Vorerst:
- Zeile 9: Die Klasse [FormInt] implementiert zwei Schnittstellen:
- ModelDriven, das nur eine Methode enthält, nämlich getModel in Zeile 16
- SessionAware, das nur eine Methode hat, nämlich setSession in Zeile 41
- Zeilen 16–21: Implementierung der ModelDriven-Schnittstelle. Zur Erinnerung: Diese Schnittstelle ermöglicht es, das Modell einer Ansicht an eine externe Klasse zu delegieren, in diesem Fall an die folgende Klasse [FormIntModel]:
package example;
public class FormIntModel {
// constructor without parameters
public FormIntModel() {
}
// form fields
private String int1;
private Integer int2;
private Integer int3;
private Integer int4;
private Integer int5;
private String int6;
// raz model
public void clearModel(){
int1=null;
int2=null;
int3=null;
int4=null;
int5=null;
int6=null;
}
// getters and setters
...
}
Das Modell [FormIntModel] verfügt über sechs Felder, die den sechs Eingabefeldern in der Ansicht [FormInt.jsp] entsprechen. Diese sechs Felder nehmen die übermittelten Werte entgegen. Vier davon sind vom Typ Integer. Daher stellt sich bei ihnen das Problem der Konvertierung von String in Integer. Mit der Methode clearModel können Sie das Modell zurücksetzen.
Kehren wir zur Methode getModel der Aktion [FormInt] zurück:
// action model
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
- Zeilen 3–5: Das Modell wird aus der Sitzung abgerufen. Ist es dort nicht vorhanden, wird eine Instanz des Modells erstellt und in die Sitzung aufgenommen.
- Zeile 6: Während bei jeder neuen Anfrage an die Aktion eine Instanz der Aktion erstellt wird, verbleibt deren Modell in der Sitzung.
Wir sehen, dass die Klasse keine Eingabemethode definiert, die übergeordnete Klasse jedoch über eine verfügt, die den Eingabeschlüssel zurückgibt. Durch Aufruf dieser Methode wird die Ansicht [FormInt.jsp] angezeigt, die wir nun vorstellen werden.
11.5.3. Die Ansicht [FormInt.jsp]
Die Ansicht [FormInt.jsp] sieht wie folgt aus:
![]() |
- in [1] das leere Formular
- in [2] das Formular nach der Validierung falscher Parameter.
Der Code lautet wie folgt:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Form.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="FormInt.message"/></h2>
<s:form name="formulaire" action="FormInt">
<s:textfield name="int1" key="int1.prompt"/>
<s:textfield name="int2" key="int2.prompt"/>
<s:textfield name="int3" key="int3.prompt"/>
<s:textfield name="int4" key="int4.prompt"/>
<s:textfield name="int5" key="int5.prompt"/>
<s:textfield name="int6" key="int6.prompt"/>
<s:submit key="Form.submitText" method="execute"/>
</s:form>
<br/>
<s:url id="url" action="FormInt" method="cancel"/>
<s:a href="%{url}"><s:text name="Form.cancelText"/></s:a>
<br/>
<s:url id="url" action="FormInt" method="clearModel"/>
<s:a href="%{url}"><s:text name="Form.clearModel"/></s:a>
</body>
</html>
- Zeilen 12–17: Die sechs Eingabefelder entsprechen den sechs Feldern des [FormIntModel]-Modells für die [FormInt]-Aktion. Bei der Anzeige der Ansicht werden die value-Attribute der Eingabefelder für die von diesen Feldern angezeigten Werte verwendet. Fehlt das value-Attribut, wird das name-Attribut verwendet.
- Zeile 12: Das Eingabefeld ist (name) mit dem Feld int1 der Aktion oder ihres Modells verknüpft, sofern die Aktion die Schnittstelle ModelDriven implementiert. Dies ist hier der Fall. Dies gilt auch für alle anderen Felder.
- Zeile 18: Die Schaltfläche [Submit] übermittelt die Eingaben an die in Zeile 11 definierte Aktion [FormInt]. Deren execute-Methode wird ausgeführt.
- Zeilen 21–22: Der Link [Cancel] führt die Methode [FormInt.cancel] aus.
- Zeilen 24–25: Der Link [Clear Model] führt die Methode [FormInt.clearModel] aus.
11.5.4. Die Ansicht [ConfirmationFormInt.jsp]
![]() |
Sie wird angezeigt, wenn alle Eingaben im Formular [FormInt.jsp] gültig sind.
- In [1] werden gültige Werte übermittelt
- In [2] die Bestätigungsseite
Der Code für die Ansicht [ConfirmationInt.jsp] lautet wie folgt:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:text name="Confirmation.titre"/></title>
<s:head/>
</head>
<body background="<s:url value="/ressources/standard.jpg"/>">
<h2><s:text name="Confirmation.message"/></h2>
<table border="1">
<tr>
<th><s:text name="Confirmation.champ"/></th>
<th><s:text name="Confirmation.valeur"/></th>
</tr>
<tr>
<td><s:text name="int1.prompt"/></td>
<td><s:property value="int1"/></td>
</tr>
<tr>
<td><s:text name="int2.prompt"/></td>
<td><s:property value="int2"/></td>
</tr>
<tr>
<td><s:text name="int3.prompt"/></td>
<td><s:property value="int3"/></td>
</tr>
<tr>
<td><s:text name="int4.prompt"/></td>
<td><s:property value="int4"/></td>
</tr>
<tr>
<td><s:text name="int5.prompt"/></td>
<td><s:property value="int5"/></td>
</tr>
<tr>
<td><s:text name="int6.prompt"/></td>
<td><s:property value="int6"/></td>
</tr>
</table>
<br/>
<s:url id="url" action="FormInt" method="input"/>
<s:a href="%{url}"><s:text name="Confirmation.lien"/></s:a>
</body>
</html>
Um diesen Code zu verstehen, denken Sie daran, dass die Ansicht angezeigt wird, nachdem die Klasse [FormInt] instanziiert wurde. Die Felder dieser Klasse und ihres Modells [FormIntModel] sind daher für die Ansicht zugänglich.
- Zeilen 16–38: Die Werte der sechs Felder werden angezeigt
- Zeilen 42–43: Ein Link zur Aktion [FormInt]. Der für diesen Link generierte Code lautet wie folgt:
<a href="/exemple-09/example/FormInt!input.action">Formulaire de test</a>
Die spezifische URL des Links gibt an, dass die Eingabemethode der Aktion [FormInt] die Anfrage bearbeiten muss. Erinnern Sie sich an die Konfiguration der Aktion [FormInt] in [example.xml]:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
Die Eingabemethode der Klasse [FormInt] entspricht der ihrer übergeordneten Klasse ActionSupport. Die Eingabemethode der Klasse [FormInt] wird ausgeführt, nachdem die Interceptors ausgeführt wurden
![]() |
Wir wissen, dass der Aufruf der Eingabemethode vom Validierungs-Interceptor ignoriert wird. Daher findet keine Validierung statt.
Die Ansicht [FormInt.jsp] wird angezeigt:
![]() |
In [2] werden die Eingabefelder auf ihre Standardwerte zurückgesetzt. Das mag normal erscheinen, ist es aber nicht. Da die Aktion [FormInt] aufgerufen wurde, wurde die zugehörige Klasse [FormInt] instanziiert. Da diese Klasse die Schnittstelle ModelDriven implementiert, wurde ihre Methode getModel aufgerufen:
// action model
public Object getModel() {
if (session.get("model") == null) {
session.put("model", new FormIntModel());
}
return session.get("model");
}
Wir sehen, dass das Modell der Aktion aus der Sitzung abgerufen wird. Im vorherigen Schritt wurde dieses Modell mit den übermittelten Werten aktualisiert. Wir rufen daher diese Werte ab. Hätten wir das Modell nicht in die Sitzung geschrieben, hätten wir in der Ansicht [FormInt.jsp] sechs leere Felder gehabt.
11.5.5. Die Aktion [FormInt!clearModel]
Die Aktion [FormInt!clearModel] wird durch Klicken auf den Link [Clear Model] ausgelöst:
![]() |
- in [1] das Formular nach einer falschen Eingabe
- in [2] das Formular nach dem Klicken auf den Link [Clear Model].
Die Methode [FormInt.clearModel] lautet wie folgt:
@SkipValidation
public String clearModel() {
// close to the model
((FormIntModel) getModel()).clearModel();
// result
return INPUT;
}
- Zeile 1: Es ist keine Validierung durchzuführen. Wir verwenden die Annotation @SkipValidation, um dies anzugeben. Der Validierungs-Interceptor führt daher keine Validierungen durch.
- Zeile 4: Die Methode [FormIntModel].clearModel wird ausgeführt. Wir sind ihr bereits begegnet. Sie setzt die sechs Felder des Modells auf null zurück.
- Zeile 7: Die Methode gibt den Eingabeschlüssel zurück.
Zurück zur Konfiguration der [FormInt]-Aktion:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
Wir sehen, dass die Eingabetaste die Ansicht [FormInt.jsp] anzeigt. Diese Ansicht zeigt die sechs Felder des Modells an. Da diese leer sind, zeigt die Ansicht sechs leere Felder an [2].
11.5.6. Die Aktion [FormInt!cancel]
Die Aktion [FormInt!cancel] wird durch Klicken auf den Link [Abbrechen] ausgelöst:
![]() |
- in [1] das Formular nach einer falschen Eingabe
- in [2], die Startseite nach dem Klicken auf den Link [Abbrechen].
Die Methode [FormInt.cancel] lautet wie folgt:
public String cancel() {
// cleaning the model
((FormIntModel) getModel()).clearModel();
// result
return "cancel";
}
- Zeile 1: Beachten Sie, dass der Methode keine SkipValidation-Annotation vorangestellt ist. Wir möchten jedoch keine Validierungen durchführen. Die Methode „cancel“ ist eine der vier Methoden (input, back, cancel, browse), die vom Validierungs-Interceptor ignoriert werden, daher ist die SkipValidation-Annotation nicht erforderlich.
- Zeile 3: Dies löscht das Modell
- Zeile 5: Hier wird der Schlüssel „cancel“ zurückgegeben
Zurück zur Konfiguration der [FormInt]-Aktion:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
Wir sehen, dass der Schlüssel „cancel“ nach einer clientseitigen Weiterleitung die Ansicht [Home.jsp] anzeigt. Dies wird in Ansicht [2] dargestellt.
11.6. Der Validierungsprozess
Wir werden uns nun mit der Validierung der sechs Eingabefelder befassen, die den folgenden sechs Feldern im Modell zugeordnet sind:
// champs du formulaire
private String int1;
private Integer int2;
private Integer int3;
private Integer int4;
private Integer int5;
private String int6;
Diese Validierung findet jedes Mal statt, wenn die Klasse [FormInt] instanziiert wird und die ausgeführte Methode vom Validierungs-Interceptor nicht ignoriert wird. Sie wird gesteuert durch:
- der Datei [FormInt-validation.xml], sofern sie sich im selben Ordner wie die Klasse [FormInt] befindet
- der Methode [FormInt.validate], sofern diese vorhanden ist.
![]() |
- in [1]: die für den Validierungsprozess erforderliche Datei [xwork-validator-1.0.2.dtd]
- in [2]: die Datei [FormInt-validation.xml] im selben Ordner wie die Klasse [FormInt]
Die Datei [FormInt-validation.xml] sieht wie folgt aus:
<!--
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-->
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//
EN" "http://localhost:8084/exemple-09/example/xwork-validator-1.0.2.dtd">
<validators>
<field name="int1" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int1.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{2}$</param>
<param name="trim">true</param>
<message key="int1.error"/>
</field-validator>
</field>
<field name="int2" >
...
</field>
...
</validators>
- in [3] die URL der DTD (Document Type Definition) für die Validierungsdatei. Diese muss zugänglich sein; andernfalls wird die Validierungsdatei nicht verwendet.
- in [7], die URL der von der Anwendung verwendeten DTD. Wir haben die DTD-Datei im Ordner [example] des Projekts example-09 [1] abgelegt, damit sie auch ohne Internetzugang verfügbar ist.
- Zeilen 11–20: Legen Sie die Validierungsbedingungen für den Parameter int1 fest, der dem Feld int1 im Modell zugeordnet ist.
Das Tag mit dem Namen int1 im Formular lautet wie folgt:
<s:textfield name="int1" key="int1.prompt" />
Das Feld „int1“ im Modell ist wie folgt deklariert:
private String int1;
- Zeilen 12–14: Überprüfen Sie, ob der Parameter „int1“ vorhanden ist (nicht null) und eine Länge ungleich Null hat. Ist dies nicht der Fall, wird dem Eingabefeld eine Fehlermeldung zugeordnet. Diese ist in [FormInt.properties] wie folgt definiert:
int1.error=Tapez un nombre entier positif de deux chiffres
Liegt ein Fehler vor, wird der Validierungsprozess für den Parameter int1 abgebrochen (short-circuit=true).
- Zeilen 15–19: Die Gültigkeit des Parameters „int1“ wird mithilfe eines regulären Ausdrucks überprüft.
- Zeile 16: Der reguläre Ausdruck, in diesem Fall zwei Ziffern ohne Vor- oder Nachlauf.
- Zeile 17: Vor dem Abgleich mit dem regulären Ausdruck werden führende und nachfolgende Leerzeichen aus dem Parameter int1 entfernt.
- Zeile 18: Die Fehlermeldung, falls vorhanden. Sie ist dieselbe wie beim vorherigen Validator.
Schauen wir uns an, wie das funktioniert:
![]() |
- in [1], eine falsche Eingabe für das Feld int1
- in [2] die Seite zurückgegeben:
- Die Fehlermeldung für den Schlüssel „int1.error“ wird angezeigt. Sie ist rot.
- Die Bezeichnung des fehlerhaften Feldes ist ebenfalls rot.
- Der fehlerhafte Eintrag wird erneut angezeigt. Dies muss berücksichtigt werden, da es sich nicht unbedingt um das Standardverhalten handelt.
Wir haben gesehen, dass die Formularvalidierung die Ausführung der Methode [FormInt].execute auslöst, wenn die Anfrage alle Interceptors, insbesondere den Validierungs-Interceptor, erfolgreich durchläuft:
![]() |
- Wenn die Anfrage die `execute`-Methode der Aktion erreicht, gibt diese, wie wir gesehen haben, den Schlüssel „success“ an den Controller zurück.
- Wenn der Validierungs-Interceptor die Anfrage stoppt, weil die geprüften Parameter ungültig sind, wird der Schlüssel `input` an den Controller zurückgegeben.
Da die [FormInt]-Aktion wie folgt konfiguriert ist:
<action name="FormInt" class="example.FormInt">
<result name="input">/example/FormInt.jsp</result>
<result name="cancel" type="redirect">/example/Accueil.jsp</result>
<result name="success">/example/ConfirmationFormInt.jsp</result>
</action>
Bei einem Validierungsfehler wird die Ansicht [FormInt.jsp] angezeigt, d. h. das Formular. Struts-Tags sind so konzipiert, dass sie alle damit verbundenen Fehlermeldungen anzeigen. Wir sehen daher die Ansicht [FormInt.jsp] mit Fehlermeldungen, die den verschiedenen Feldern zugeordnet sind. Dies ist in Ansicht [2] dargestellt.
Betrachten wir nun die Validierung des Feldes int2, das im Modell wie folgt deklariert ist:
private Integer int2;
Die Validierung des Feldes „int2“ in [FormInt-validation.xml] lautet wie folgt:
<field name="int2" >
<field-validator type="required" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
</field>
- Zeilen 2–4: Überprüfen Sie, ob der Parameter „int2“ vorhanden ist.
- Zeilen 5–7: Überprüfen Sie, ob die Konvertierung von String zu Integer möglich ist.
- Zeilen 3, 6: Die Fehlermeldung für den Schlüssel „int2.error“ lautet wie folgt:
int2.error=Tapez un nombre entier
Die Validierung für das Integer-Feld „int3“ im Modell in [FormInt-validation.xml] lautet wie folgt:
<field name="int3" >
<field-validator type="required" short-circuit="true">
<message key="int3.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">-1</param>
<message key="int3.error"/>
</field-validator>
</field>
- Zeilen 8–11: Überprüfen Sie, ob das Feld „int3“ eine ganze Zahl >= -1 ist
- Zeilen 3, 7: Die Fehlermeldung für den Schlüssel „int3.error“ lautet wie folgt:
int3.error=Tapez un nombre entier >=-1
Die Validierung des Integer-Feldes int4 im Modell in [FormInt-validation.xml] lautet wie folgt:
<field name="int4" >
<field-validator type="required" short-circuit="true">
<message key="int4.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="max">10</param>
<message key="int4.error"/>
</field-validator>
</field>
- Zeilen 8–11: Überprüfen, ob es sich um eine ganze Zahl <=10 handelt
- Zeilen 3, 7: Die Fehlermeldung für den Schlüssel „int4.error“ lautet wie folgt:
int4.error=Tapez un nombre entier <=10
Die Validierung für das Integer-Feld int5 im Modell in [FormInt-validation.xml] lautet wie folgt:
<field name="int5" >
<field-validator type="required" short-circuit="true">
<message key="int5.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="int5.error"/>
</field-validator>
</field>
- Zeilen 5–9: Überprüfen Sie, ob der Wert eine ganze Zahl im Bereich [1, 10] ist.
- Zeilen 3, 8: Die Fehlermeldung für den Schlüssel „int5.error“ lautet wie folgt:
int5.error=Tapez un nombre entier dans l''intervalle [1,10]
Die Validierung für das String-Feld int6 im Modell in [FormInt-validation.xml] lautet wie folgt:
<field name="int6" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int6.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{1,2}$</param>
<param name="trim">true</param>
<message key="int6.error"/>
</field-validator>
</field>
- Zeilen 5–9: Überprüfen, ob int6 eine zweistellige Zeichenfolge ist.
- Zeilen 3, 8: Die Fehlermeldung für den Schlüssel „int6.error“ lautet wie folgt:
int6.error=Tapez un nombre entier dans l''intervalle [2,20]
Die vorherige Validierung prüft nicht, ob der Parameter int6 eine ganze Zahl im Bereich [2,20] ist. Diese Prüfung wird in der Methode [FormInt].validate durchgeführt, die nach der Verarbeitung der Datei [FormInt-validation.xml] ausgeführt wird. Diese Methode lautet wie folgt:
// validation
@Override
public void validate() {
// valid int6 input?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
}
- Zeile 5: Wir prüfen, ob Fehler im Zusammenhang mit dem Feld „int6“ vorliegen. Wenn ja, brechen wir hier ab.
- Zeile 6: Wenn keine Fehler aufgetreten sind, rufen wir das int6-String-Feld aus dem Modell ab und konvertieren es in eine Ganzzahl.
- Zeile 7: Wir überprüfen, ob die abgerufene Ganzzahl im Bereich [2,20] liegt.
- Zeile 8: Ist dies nicht der Fall, wird dem Feld „int6“ eine Fehlermeldung zugeordnet. Diese Fehlermeldung wird mithilfe des Schlüssels „int6.error“ aus der Meldungsdatei abgerufen.
Werden am Ende dieses Validierungsprozesses Fehler gefunden, wird der Aufruf der Methode [FormInt].execute abgebrochen und der Eingabeschlüssel an den Struts-Controller zurückgegeben.
![]() |
11.7. Abschließende Details
Wir haben verschiedene Möglichkeiten zur Eingabe von Ganzzahlen kennengelernt. Diese sind nicht alle gleichwertig. Betrachten Sie zum Beispiel die Eingabefelder int5 und int6:
In der Ansicht [FormInt.jsp] sind sie wie folgt deklariert:
<s:textfield name="int5" key="int5.prompt"/>
<s:textfield name="int6" key="int6.prompt"/>
Ihr Modell ist in [FormIntModel.java] deklariert:
private Integer int5;
private String int6;
Das Feld int5 ist vom Typ Integer, während das Feld int6 vom Typ String ist. Ihre Validierungsregeln unterscheiden sich:
<field name="int5" >
<field-validator type="required" short-circuit="true">
<message key="int5.error"/>
</field-validator>
<field-validator type="conversion" short-circuit="true">
<message key="int2.error"/>
</field-validator>
<field-validator type="int" short-circuit="true">
<param name="min">1</param>
<param name="max">10</param>
<message key="int5.error"/>
</field-validator>
</field>
<field name="int6" >
<field-validator type="requiredstring" short-circuit="true">
<message key="int6.error"/>
</field-validator>
<field-validator type="regex" short-circuit="true">
<param name="expression">^\d{1,2}$</param>
<param name="trim">true</param>
<message key="int6.error"/>
</field-validator>
</field>
Die Validierung des Felds „int6“ erfolgt durch die Methode „validate“ der Aktion [FormInt]:
public void validate() {
// valid int6 input?
if (getFieldErrors().get("int6") == null) {
int int6 = Integer.parseInt(((FormIntModel) getModel()).getInt6());
if (int6 < 2 || int6 > 20) {
addFieldError("int6", getText("int6.error"));
}
}
Obwohl unterschiedlich formuliert, zielen beide Validierungsregeln darauf ab, zu überprüfen, ob der eingegebene Wert eine ganze Zahl innerhalb eines bestimmten Bereichs ist. Das Verhalten der Felder int5 und int6 unterscheidet sich jedoch zur Laufzeit, wie die folgenden Screenshots zeigen:
![]() |
- in [1] die gleiche falsche Eingabe für beide Felder
- in [2] die angezeigte Fehlerseite. Die beiden Felder weisen unterschiedliche Fehlermeldungen auf.
- In [3] erscheint eine unerwünschte Meldung für das Feld „int5“, da es auf Englisch ist. Dies resultiert aus der fehlgeschlagenen Konvertierung von String zu Integer. Außerdem gibt es eine Ausnahme in den Apache-Protokollen:
Seltsamerweise suchte Struts nach einer Methode FormIntModel.setInt5(String value), konnte diese jedoch nicht finden.
Der Schlüssel für die Fehlermeldung lautet xwork.default.invalid.fieldvalue. Um sie ins Französische zu übersetzen, ordnen Sie diesem Schlüssel einfach einen französischen Text zu. Wir fügen daher die folgende Zeile in die Datei [messages.properties] ein:
...
xwork.default.invalid.fieldvalue=Valeur invalide pour le champ "{0}".
11.8. Fazit
Damit ist unsere Untersuchung dieser ersten Anwendung zur Parametervalidierung abgeschlossen. Die Erläuterung war komplex. Wir werden nun ähnliche Anwendungen betrachten. Daher werden wir nur auf die Änderungen eingehen.














