3. Przetwarzanie formularza przez kontroler
Zajmiemy się teraz przetwarzaniem wartości formularza przez kontroler, gdy użytkownik kliknie przycisk [Envoyer] w formularzu.
3.1. Plik struts-config.xml
Nowy plik konfiguracyjny kontrolera Struts o nazwie struts-config.xml wygląda następująco:
<?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.FormulaireBean"
/>
</form-beans>
<action-mappings>
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
<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>
Zmiany zostały zaznaczone:
- pojawia się sekcja <form-beans>. Służy ona do definiowania klas powiązanych z każdym formularzem w aplikacji. Musi być tyle tagów <form-bean>, ile jest różnych formularzy w aplikacji. W tym przypadku mamy tylko jeden formularz, więc tylko jedną sekcję <form-bean>. Dla każdego formularza musimy zdefiniować:
- jego nazwę (atrybut name)
- nazwę klasy pochodnej od ActionForm, odpowiedzialnej za przechowywanie wartości formularza (atrybut type)
Te dwa atrybuty nie mogą być dowolne. Muszą być identyczne z tymi używanymi w tagu <html:form> kodu HTML formularza. Przypomnijmy ten kod dla formularza (nazwa, wiek):
Formularz należy zadeklarować w ten sam sposób w pliku struts-config.html. Tak właśnie zrobiono w tym przypadku:
- Zmieniła się konfiguracja akcji /main. Akcja ta odpowiada za przetwarzanie wartości z formularza. Należy więc podać w niej informacje, których potrzebuje:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Serwlet /main przetworzy formularz, któremu należy nadać nazwę. Zadanie to realizuje atrybut name. Nazwa ta musi odnosić się do atrybutu name jednej z sekcji <form-bean>, w tym przypadku frmPersonne.
Atrybut scope="session" wskazuje, że wartości formularza muszą zostać zapisane w sesji. Nie zawsze jest to konieczne. W tym przypadku jednak jest. W widokach /reponse.do i /erreurs.do znajdują się bowiem linki prowadzące z powrotem do formularza. W obu przypadkach chcemy wyświetlić formularz z wartościami wprowadzonymi przez użytkownika podczas poprzedniej wymiany danych między klientem a serwerem. Stąd konieczność zapisania formularza w sesji.
Atrybut „validate” wskazuje, czy należy wywołać metodę „validate” obiektu frmPersonne, czy też nie. Metoda ta służy do sprawdzania poprawności danych formularza. W tym przypadku wskazujemy, że dane muszą zostać sprawdzone, co oznacza, że będziemy musieli napisać metodę „validate” w klasie FormulaireBean. Metoda validate** formularza jest wywoływana przez kontroler Struts przed wywołaniem serwletu /main**. Zwraca ona obiekt typu **ActionErrors, który jest analogiczny do listy błędów. Jeśli lista ta istnieje i nie jest pusta, kontroler Struts zatrzyma się w tym miejscu i wyśle jako odpowiedź widok wskazany przez atrybut input. Widok otrzyma w żądaniu listę ActionErrors, którą będzie mógł wyświetlić za pomocą tagu <html:errors>. Powyżej stwierdzamy, że w przypadku wystąpienia błędów serwlet /main musi wysłać widok /erreurs.do. Przypomnijmy, że ten widok jest powiązany z następującym widokiem /URL /vues/erreurs.reponse.jsp**:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<html:errors/>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
Widok prawidłowo wykorzystuje tag <html:errors>, który umożliwia wyświetlenie listy błędów. Na tej liście błędów nie znajdują się komunikaty o błędach, lecz identyfikatory komunikatów zawartych w pliku, do którego odwołuje się tag <message-resources> (uwaga: „resources” z jednym „s”):
Poniższy tag wskazuje, że plik zawierający komunikaty używane przez aplikację znajduje się w pliku WEB-INF/classes/ressources/personneressources.properties:

Co znajduje się w tym pliku? Jest to plik właściwości odpowiadający klasie Properties w Javie, czyli zbiór wierszy w formacie klucz=wartość:
errors.header=<ul>
errors.footer=</ul>
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
Ten plik komunikatów pełni co najmniej dwie funkcje:
- umożliwia zmianę komunikatów aplikacji bez konieczności jej ponownej kompilacji
- umożliwia internacjonalizację aplikacji Struts. Można bowiem utworzyć kilka plików zasobów, po jednym dla każdego języka. Struts automatycznie wykorzysta właściwy plik komunikatów, pod warunkiem przestrzegania określonych standardów w nazewnictwie tych plików.
- Jeśli metoda validate formularza zwraca pustą listę błędów, wówczas kontroler Struts wywołuje metodę execute serwletu ForwardAction. Ważne jest, aby zrozumieć, że uruchomienie metody `execute` serwletu oznacza, iż dane formularza zostały uznane za prawidłowe (o ile oczywiście zostały sprawdzone przy `validate="true"`). To właśnie w metodzie `execute` serwletu powiązanego z akcją programista faktycznie przetwarza formularz. To właśnie tam znajduje się sedno przetwarzania (logika aplikacji, wykorzystanie klas biznesowych i klas dostępu do danych). Ostatecznie metoda zwraca wynik typu ActionForward, który wskazuje konstruktorowi, który widok należy wysłać w odpowiedzi do klienta. W tym przypadku wykorzystaliśmy predefiniowaną akcję ForwardAction z biblioteki Struts. Jej metoda `execute` zwraca po prostu obiekt typu ActionForward, który wskazuje na obiekt URL określony przez atrybut `parameter`:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Jeśli więc dane z formularza są prawidłowe, akcja /main zwróci widok /vues/main.html, z którego już korzystaliśmy.
3.2. Nowa klasa FormulaireBean
Stworzyliśmy już pierwszą wersję klasy FormulaireBean, której zadaniem jest przechowywanie danych (imię, wiek) z formularza formulaire.personne.jsp. Ta wersja nie sprawdzała poprawności danych. Teraz musimy to zrobić, ponieważ w pliku struts-config.xml wskazaliśmy, że dane z formularza powinny zostać zweryfikowane (validate="true") przed przekazaniem ich do serwletu ForwardAction. Kod klasy wygląda następująco:
package istia.st.struts.personne;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class FormulaireBean
extends ActionForm {
// imię
private String nom = null;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
}
// wiek
private String age = null;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
// weryfikacja
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// obsługa błędów
ActionErrors erreurs = new ActionErrors();
// nazwisko nie może być puste
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
// wiek musi być dodatnią liczbą całkowitą
}
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// wiek musi być dodatnią liczbą całkowitą
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// zwracamy listę błędów
}
} //if
// zwracana jest lista błędów
return erreurs;
}
}
Nowością jest kod metody validate. Metoda ta jest wywoływana przez kontroler Struts po tym, jak kontroler ten przypisał do atrybutów nom i age klasy wartości z pól formularza o tych samych nazwach. Metoda ta musi sprawdzić poprawność atrybutów nom i age. Powyższy kod jest dość łatwy do zrozumienia:
- tworzona jest pusta lista błędów (ActionErrors błędy)
- sprawdzane jest pole „nom”. Jeśli jest puste, do listy błędów dodawany jest błąd za pomocą metody ActionErrors.add("klucz", ActionError).
- To samo dzieje się, jeśli pole „age” nie jest liczbą całkowitą.
- Metoda validate zwraca do kontrolera Struts listę błędów (ActionErrors błędy). Jeśli błędy są równe null lub jeśli erreurs.size() jest równe 0, kontroler uznaje, że nie wystąpiły żadne błędy. Następnie uruchomi metodę `execute` klasy `Action` powiązanej z daną akcją (type="org.apache.struts.actions.ForwardAction"). W przeciwnym razie zwróci widok powiązany z sytuacją wystąpienia błędów w formularzu (input="/erreurs.do").
Dodajemy błąd do listy ActionErrors błędów za pomocą ActionErrors.add("cléErreur", new ActionError("cléMessage"[,param0, param1, param2, param3])). Pierwszy parametr „cléErreur” służy do jednoznacznego wskazania elementu ActionError na liście ActionErrors, podobnie jak w słowniku. Może to być dowolna wartość. ActionError to obiekt, który przypisuje się do komunikatu o błędzie za pomocą jego konstruktora ActionError(String cléMessage[,String param0, String param1, String param2, String param3]), gdzie cléMessage to identyfikator komunikatu powiązanego z błędem oraz do 4 opcjonalnych parametrów. Identyfikator cléMessage nie jest przypadkowy. Jest to jeden z identyfikatorów znajdujących się w pliku wskazanym przez tag <message-resources> w pliku struts-config.xml:
Przypomnijmy, że ten plik (w rzeczywistości WEB-INF/classes/ressources/personneressources.properties) zawiera następujące klucze:
errors.header=<ul>
errors.footer=</ul>
personne.formulaire.nom.vide=<li>Vous devez indiquer un nom</li>
personne.formulaire.age.incorrect=<li>L'âge [{0}] est incorrect</li>
Można sprawdzić, czy klucze komunikatów używane przez metodę validate klasy FormulaireBean rzeczywiście istnieją w powyższym pliku. W przypadku każdego komunikatu o błędzie zastosowano tag HTML <li>, aby tag <html:errors> wyświetlał je jako listę HTML. Zauważyliśmy, że obiekt ActionError można utworzyć nie tylko przy użyciu klucza komunikatu, ale także z dodatkowymi parametrami:
Jeśli obiekt ActionError został utworzony z dodatkowymi parametrami (maksymalnie czterema), są one dostępne w treści komunikatu za pomocą notacji od {0} do {3}. W ten sposób metoda validate obiektu FormulaireBean tworzy obiekt ActionError z kluczem personne.formulaire.age.incorrect i dodatkowym parametrem param0 o wartości:
Komunikat powiązany w pliku .properties komunikatów z kluczem personne.formulaire.age.incorrect brzmi
{0} zostanie zastąpione wartością wieku. Na koniec komunikaty o kluczach errors.header i errors.footer zostaną zapisane odpowiednio przed i po liście błędów. W tym przypadku te dwa klucze posłużą do wstawienia tagów HTML <ul> i </ul>, które muszą otaczać tagi <li>.
3.3. Testy poprawności formularza
Jesteśmy gotowi do przeprowadzenia testów poprawności formularza. Poniżej przypominamy, gdzie należy umieścić poszczególne komponenty aplikacji:
![]() | |
![]() | |
![]() | |
![]() |
3.3.1. Test 1
Uruchommy ponownie serwer Tomcat, aby odczytał nowe pliki konfiguracyjne, a następnie wywołajmy URL http://localhost:8080/strutspersonne/formulaire.do:

Wyjaśnienia:
- w pliku struts-config.html wykorzystano następującą sekcję:
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
Jeśli przyjrzymy się kodowi HTML otrzymanej strony, zauważymy, że tag <form> tej strony wygląda następująco:
Przycisk [Envoyer], który jest przyciskiem typu „submit”, wyśle zatem dane formularza do URL /strutspersonne/main.do.
3.3.2. Test 2
Skorzystajmy z przycisku [Envoyer], pozostawiając pola wprowadzania danych puste. Otrzymujemy następującą odpowiedź:

Wyjaśnienia:
- jak wspomniano powyżej, dane z formularza zostały przesłane do pliku URL /strutspersonne/main.do. Wykorzystano wówczas następujące sekcje pliku struts-config.xml:
<form-bean
name="frmPersonne"
type="istia.st.struts.personne.FormulaireBean"
scope="session"
/>
....
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Wywołano akcję /main. Wykorzystuje ona formularz frmPersonne (name="frmPersonne"). W związku z tym kontroler Struts utworzył, w razie potrzeby, instancję obiektu klasy FormulaireBean (type="istia.st.struts.personne.FormulaireBean" w tagu form-bean). Następnie wypełnił atrybuty „nom” i „age” tego obiektu danymi z pól o tych samych nazwach w formularzu HTML:
<table>
<tr>
<td>Nom</td>
<td><html:text property="nom" size="20"/></td>
</tr>
<tr>
<td>Age</td>
<td><html:text property="age" size="3"/></td>
</tr>
<tr>
</table>
Po wykonaniu tej czynności kontroler Struts wywołał metodę validate** obiektu **FormulaireBean**, ponieważ atrybut **validate** akcji **/main ma wartość **true** w pliku konfiguracyjnym:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Metoda validate klasy FormulaireBean wygląda następująco:
// walidacja
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
// obsługa błędów
ActionErrors erreurs = new ActionErrors();
// nazwa nie może być pusta
if (nom == null || nom.trim().equals("")) {
erreurs.add("nomvide", new ActionError("personne.formulaire.nom.vide"));
// wiek musi być dodatnią liczbą całkowitą
}
if (age == null || age.trim().equals("")) {
erreurs.add("agevide", new ActionError("personne.formulaire.age.vide"));
}
else {
// wiek musi być dodatnią liczbą całkowitą
if (!age.matches("^\\s*\\d+\\s*$")) {
erreurs.add("ageincorrect", new ActionError("personne.formulaire.age.incorrect", age));
// zwracamy listę błędów
}
} //if
// zwracamy listę błędów
return erreurs;
}
Ponieważ pola [nom] i [age] były puste, powyższa metoda walidacyjna wygenerowała listę dwóch błędów, którą zwróciła do kontrolera Struts. Ponieważ wystąpiły błędy, kontroler zwrócił następnie do klienta widok powiązany z atrybutem input. Aby ustalić, o jaki widok chodziło, wykorzystał następujący fragment swojego pliku konfiguracyjnego:
<action
path="/erreurs"
parameter="/vues/erreurs.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
Ostatecznie wysłał więc widok /vues/erreurs.personne.jsp. Ma on następujący kod:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<html:errors/>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
Tag <html:errors> wyświetla po prostu listę komunikatów przesłanych mu przez kontroler Struts. Wykorzystuje on plik komunikatów wskazany przez tag <message-resources>:
Znajdują się w nim następujące klucze i komunikaty:
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>
- zapisano komunikat powiązany z kluczem errors.header
- zapisano komunikaty powiązane z różnymi kluczami z otrzymanej listy ActionErrors
- zapisano komunikat powiązany z kluczem errors.footer
3.3.3. Test 3
Skorzystajmy z linku [Retour au formulaire] na stronie błędów. Otrzymujemy następującą stronę:

Wyjaśnienia:
- link [Retour au formulaire] ma następujący kod: HTML:
Kontroler Struts wykorzystał następującą sekcję ze swojego pliku konfiguracyjnego:
<action
path="/formulaire"
parameter="/vues/formulaire.personne.jsp"
type="org.apache.struts.actions.ForwardAction"
/>
W związku z tym zwrócił widok /vues/formulaire.personne.jsp.
3.3.4. Test 4
Wypełniamy poniższy formularz, a następnie korzystamy z przycisku [Envoyer]:

Otrzymujemy następującą odpowiedź:

Wyjaśnienia: są takie same jak w przypadku testu nr 2.
3.3.5. Test 5
Korzystamy z powyższego linku [Retour au formulaire]. Otrzymujemy następującą stronę:

Zauważamy, że formularz pojawia się w stanie, w jakim go zatwierdziliśmy.
Wyjaśnienia: są takie same jak w teście nr 3, z dodatkową informacją:
- wyświetlony formularz HTML zawiera następujące tagi:
<table>
<tr>
<td>Nom</td>
<td><html:text property="nom" size="20"/></td>
</tr>
<tr>
<td>Age</td>
<td><html:text property="age" size="3"/></td>
</tr>
<tr>
</table>
Tagi <html:text> pełnią dwie funkcje:
- podczas wysyłania wartości formularza z klienta na serwer wartości pól wprowadzania danych w formularzu są przypisywane do pól o tej samej nazwie w obiekcie FormulaireBean
- podczas wysyłania przez serwer do klienta kodu HTML formularza do wyświetlenia, atrybuty value pól wprowadzania danych powiązanych z tagami <html:text> są inicjowane wartościami pól o tej samej nazwie w obiekcie FormulaireBean.
Mamy tu do czynienia z dwiema różnymi wymianami danych między klientem a serwerem:
- w pierwszej użytkownik wypełnił formularz i wysłał go do serwera
- w drugiej sytuacji użytkownik skorzystał z linku [Retour au formulaire], aby powrócić do formularza.
Jedynym sposobem, aby w drugiej interakcji formularz mógł zostać ponownie wyświetlony z pierwotnymi wartościami, jest umieszczenie tych wartości w sesji klienta. Tak właśnie zrobiono w sekcji konfigurującej akcję /main:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Gdybyśmy ustawili scope="request", dane z formularza nie zostałyby zapisane w sesji i nie odzyskamy wówczas ich wartości podczas drugiej wymiany danych.
3.3.6. Test 6
Wróćmy do formularza, aby tym razem wprowadzić prawidłowe dane:

Prześlijmy formularz. Otrzymujemy następujący wynik:

Wyjaśnienia:
- ponieważ przycisk [Envoyer] wysyła wartości formularza do URL /strutspersonne/main.do, mamy te same wyjaśnienia, co w teście nr 2, aż do momentu powrotu do kontrolera Struts z wynikiem ActionErrors z metody validate w FormulaireBean. Jednak w tym przypadku lista ta jest pusta. Kontroler wykorzystuje wówczas nową część konfiguracji akcji /main:
<action
path="/main"
name="frmPersonne"
scope="session"
validate="true"
input="/erreurs.do"
parameter="/vues/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
Kontroler Struts tworzy, w razie potrzeby, obiekt typu wskazanego przez atrybut „type”. Wywoływana jest metoda „execute” tej klasy, która musi zwrócić obiekt typu ActionForward określający widok, jaki kontroler ma wysłać jako odpowiedź do klienta. W tym przypadku atrybut „type” wskazuje na predefiniowaną klasę ForwardAction. Metoda execute** tej klasy nie wykonuje żadnych działań i ogranicza się do zwracania obiektu typu ActionForward, wskazującego na widok zdefiniowany przez atrybut parameter**, w tym przypadku widok /vues/main.html. Jest to faktycznie widok, który kontroler zwrócił.
3.3.7. Test 7
Ponownie żądamy widoku /formulaire.do:

Formularz pojawia się w takiej postaci, w jakiej został zatwierdzony. Wyjaśnienie tego zjawiska podano już wcześniej. Dzięki konfiguracji (scope="session") zastrzeżono, aby formularz pozostawał w sesji. Jego wartości są zatem zachowywane podczas wymiany danych między klientem a serwerem.
Jesteśmy już prawie na finiszu. Pozostaje nam jeszcze utworzyć właściwą akcję na wypadek, gdyby dane z formularza były prawidłowe. Na razie, aby uprościć naszą demonstrację, wykorzystaliśmy predefiniowaną akcję ForwardAction.
3.4. Nowa konfiguracja akcji /main
Nie zmieniamy obecnego pliku konfiguracyjnego struts-config.xml, poza modyfikacją sekcji /main w następujący sposób:
<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>
Atrybut „type” wskazuje teraz inną klasę o nazwie FormulaireAction, którą będziemy musieli utworzyć. To właśnie metoda „execute” tej klasy zostanie wykonana, jeśli dane z formularza frmPersonne są prawidłowe. Wskazaliśmy, że metoda **execute wykonała swoje zadanie i zwróciła obiekt typu **ActionForward, określający widok, który kontroler miał zwrócić klientowi. Często istnieje kilka możliwych widoków w zależności od wyniku przetwarzania formularza. Lista różnych możliwych widoków jest zawarta w tagach <forward> umieszczonych w tagu <action>. Składnia takiego tagu jest następująca:
dowolna nazwa jednoznacznie identyfikująca widok | |
URL widoku powiązanego z kluczem |
3.5. Klasa FormulaireAction
Napisanie klasy FormulaireAction polega zasadniczo na napisaniu jej metody execute:
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;
public class FormulaireAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException,ServletException {
// formularz jest poprawny, w przeciwnym razie nie dotarliśmy byśmy do tego miejsca
FormulaireBean formulaire=(FormulaireBean)form;
request.setAttribute("nom",formulaire.getNom());
request.setAttribute("age",formulaire.getAge());
return mapping.findForward("reponse");
}//wykonaj
}
Metoda execute przyjmuje cztery parametry:
- Mapowanie ActionMapping: obiekt „obraz” przedstawiający konfigurację aktualnie wykonywanej akcji, a więc w tym przypadku obraz następującej konfiguracji:
<action
path="/main"
name="frmPersonne"
validate="true"
input="/erreurs.do"
type="istia.st.struts.personne.FormulaireAction"
>
<forward name="reponse" path="/reponse.do"/>
</action>
W ten sposób akcja ma dostęp do kluczy powiązanych z widokami, które mogą zostać zwrócone klientowi po zakończeniu akcji. Wywoływana metoda powinna zwrócić jeden z tych kluczy.
- ActionForm form: obiekt typu bean, w którym znajdują się wartości formularza wykorzystywanego przez bieżącą akcję. W tym przypadku jest to obiekt frmPersonne typu FormulaireBean. W ten sposób akcja ma dostęp do wartości formularza.
- HttpServletRequest request: żądanie klienta, które mogło zostać wzbogacone przez różne serwlety. Akcja ma zatem dostęp do wszystkich parametrów pierwotnego żądania (request.getParameter), a także do wszystkich atrybutów dodanych do tego pierwotnego żądania (request.getAttribute). W naszym przykładzie metoda `execute` wzbogaca żądanie, dodając do niego imię i wiek. Jest to tutaj całkowicie zbędne, ponieważ obie te wartości już tam są, ale jako parametry, a nie jako atrybuty. Kod ten służy wyłącznie jako przykład.
- HttpServletResponse response: odpowiedź, która zostanie wysłana do klienta. Akcja mogłaby wzbogacić tę odpowiedź. Tutaj tego nie robi.
Mamy tu do czynienia ze szczególnym przypadkiem. Metoda **execute praktycznie nie ma nic do zrobienia. Musi jedynie wskazać, że następnym widokiem jest widok **/reponse.do**, oraz umieścić w żądaniu informację, że widok ten otrzyma dane „nazwa” i „wiek”, które ma wyświetlić. Czyni to za pomocą metody findForward klasy ActionMapping, która jako parametr przyjmuje jeden z kluczy znalezionych w tagach forward** w konfiguracji akcji. W tym przypadku występuje tylko jeden taki tag:
Nasza metoda execute zwraca zatem ActionForward z kluczem „reponse”, wskazującym, że należy wysłać widok /reponse.do.
3.6. Testy dla FormulaireAction
Kompilujemy poprzednią klasę za pomocą JBuilder i umieszczamy wygenerowany plik .class w katalogu WEB-INF/classes:

Modyfikujemy widok /vues/reponse.personne.jsp:
<%
// pobieramy dane: imię, wiek
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td><%= nom %>
</tr>
<tr>
<td>Age</td>
<td><%= age %>
</tr>
</table>
<html:link page="/formulaire.do">
Retour au formulaire
</html:link>
</body>
</html>
Widok pobiera informacje o nazwisku i wieku z atrybutów otrzymanego zapytania. Żądamy formularza od URL http://localhost:8080/strutspersonne/formulaire.do, a następnie go wypełniamy:

Korzystamy z przycisku [Envoyer] i otrzymujemy następującą odpowiedź:

Wyjaśnienia:
- Na początku procesu wykorzystamy wyjaśnienie podane dla testu nr 2. Przypomnijmy konfigurację akcji /main:
<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>
- po wysłaniu formularza do kontrolera o numerze URL /main.do, kontroler ten utworzył lub ponownie wykorzystał obiekt frmPersonne typu FormulaireBean i umieścił w nim wartości z formularza
- wywołano metodę validate obiektu frmPersonne. Ponieważ dane były prawidłowe, metoda validate zwróciła pustą listę ActionErrors.
- Utworzono lub ponownie wykorzystano obiekt FormulaireAction i wywołano jego metodę `execute`. Metoda ta zwróciła obiekt ActionForward z kluczem „reponse”.
- Następnie kontroler wysłał widok powiązany z kluczem „reponse”, c.a.d. /reponse.do, a tym samym /vues/reponse.personne.jsp.
- Wyświetlono widok reponse.personne.jsp z wartościami umieszczonymi w żądaniu przez metodę execute obiektu FormulaireAction.
3.7. Wniosek
Stworzyliśmy kompletną, ale prostą aplikację. Podczas jej rzeczywistego wdrażania przy użyciu Struts, Tomcat i JBuilder istnieje wiele okazji do popełnienia błędów, zwłaszcza w plikach konfiguracyjnych aplikacji o nazwie XML. Na pierwszy rzut oka prostsze może wydawać się stworzenie tej aplikacji bez Struts, przy użyciu serwletu i stron JSP. Dla początkujących jest to prawdopodobnie prawda. Jednak wraz z nabieraniem doświadczenia programowanie przy użyciu Struts staje się łatwiejsze. Wiele firm narzuca metodologię Struts w swoich projektach internetowych z następujących powodów:
- Struts jest zgodny z modelem MVC
- gdy wszyscy programiści pracują w ten sam sposób, utrzymanie aplikacji staje się łatwiejsze, ponieważ mają one standardową architekturę.



