Skip to content

4. Utilizzo di moduli dinamici

4.1. Dichiarazione del modulo dinamico

Abbiamo visto che Struts utilizza oggetti ActionForm per memorizzare i valori dei moduli HTML elaborati dai vari servlet dell'applicazione. Per ogni modulo della nostra applicazione, dobbiamo creare una classe derivata da ActionForm. Ciò può diventare rapidamente complicato poiché per ogni campo xx, dobbiamo scrivere due metodi: setXx e getXx. Struts offre la possibilità di utilizzare moduli

  • la cui struttura è dichiarata nel file struts-config.xml all'interno della sezione <form-beans>
  • , che vengono creati dinamicamente dall’ambiente Struts in base alla struttura dichiarata

Pertanto, la classe utilizzata per memorizzare i valori di nome ed età nell'applicazione strutspersonne potrebbe essere definita come segue:

    <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>

Per ogni campo del modulo, definiamo un tag <form-property> con due attributi:

  • name: il nome del campo
  • type: il suo tipo Java

Poiché i valori di un modulo inviati da un client web sono stringhe, i tipi più comunemente utilizzati sono java.lang.String per i campi a valore singolo e java.lang.String[] per i campi a valori multipli (caselle di controllo con lo stesso nome, elenchi a selezione multipla, ecc.). La classe DynactionForm, come la classe ActionForm, ha un metodo validate che non fa nulla. Per far sì che verifichi la validità dei parametri del modulo, è necessario estenderla e scrivere il metodo validate autonomamente. La dichiarazione del modulo sarà quindi la seguente:

    <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>

Dovremo scrivere noi stessi la classe istia.st.struts.personne.PersonneDynaForm.

4.2. Scrivere la classe DynaActionForm associata al modulo dinamico

In precedenza, abbiamo associato la classe istia.st.struts.personne.PersonneDynaForm al modulo (nome, età). Ora scriveremo questa classe:

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

È necessario tenere presente quanto segue:

  • la classe deriva da DynaActionForm
  • il metodo validate della classe DynaActionForm è stato riscritto. Quando viene eseguito dal controller Struts, viene costruito l'oggetto PersonneDynaForm. Esso contiene un dizionario le cui chiavi sono i campi del modulo name e age, e i cui valori sono i valori di tali campi. Per accedere a un campo all'interno dei metodi DynaActionForm, utilizzare il metodo Object get(String fieldName). Per impostare un valore per un campo, utilizzare il metodo void set(String fieldName, Object value). Fare riferimento alla definizione della classe DynaActionForm per una descrizione completa.
  • Una volta recuperati i valori dei campi name e age del modulo, il metodo validate non è diverso da quello scritto quando il modulo era associato a un oggetto ActionForm.

4.3. La nuova classe FormAction

Il file di configurazione definisce la seguente azione /main:

...
    <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>

Questa definizione è identica a quella dell'applicazione strutspersonne. L'azione /main è implementata da un oggetto di tipo FormulaireAction. Questo oggetto riceveva i valori del modulo frmPersonne in un oggetto di tipo FormulaireBean. Ora li riceve in un oggetto di tipo PersonneDynaForm. Pertanto, la classe deve essere riscritta:

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
}

È necessario tenere presente quanto segue:

  • È necessario importare la classe PersonneDynaForm, che contiene i dati del modulo, per accedere alla sua definizione
  • Il metodo execute recupera i valori dei parametri del modulo utilizzando il metodo [DynaActionForm].get.

Rispetto alla classe FormAction nell'applicazione strutspersonne, è cambiato solo il modo di accedere ai valori del modulo.

4.4. Distribuzione e test dell'applicazione strutspersonne1

4.4.1. Creazione del contesto

Abbiamo chiamato questa nuova applicazione strutspersonne1. Creiamo una nuova definizione nel file <tomcat>\conf\serveur.xml per Tomcat 4.x:

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

Una volta fatto questo, è necessario riavviare Tomcat. È possibile verificare la validità del contesto richiedendo l'URL:

http://localhost:8080/strutspersonne1/

Image

4.4.2. Le viste

Copiare la cartella views dall'applicazione strutspersonne nella cartella dell'applicazione strutspersonne1. Le viste non sono cambiate.

Image

4.4.3. Compilazione delle classi

Abbiamo due classi da creare: PersonneDynaForm e FormulaireAction, dove la seconda utilizza la prima. Possiamo crearle e compilarle utilizzando un progetto JBuilder:

Image

4.4.4. La cartella WEB-INF

Copia la cartella WEB-INF dall'applicazione strutspersonne nella cartella dell'applicazione strutspersonne1. Alcuni file sono stati modificati:

Image

Il file di configurazione struts-config.xml diventa il seguente:

<?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>

Questo file è identico a quello dell'applicazione strutspersonne, ad eccezione della definizione del modulo dinamico (sezione in riquadro).

Nella cartella WEB-INF/classes, inserire le classi compilate da JBuilder:

Image

Nella cartella WEB-INF\classes\resources, inserisci il file dei messaggi. Non è cambiato.

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>

Image

4.5. Test

Siamo pronti per i test. Di seguito sono riportati alcuni screenshot che il lettore è invitato a riprodurre.

Richiedi l'URL http://localhost:8080/strutspersonne1/formulaire.do:

Image

Fare clic sul pulsante [Invia] senza compilare i campi:

Image

Riprova inserendo un valore errato nel campo dell'età:

Image

Otteniamo la seguente risposta:

Image

Prova di nuovo, inserendo questa volta i valori corretti:

Image

Riceviamo la seguente risposta:

Image

4.6. Conclusione

L'uso di moduli dinamici semplifica la scrittura delle classi ActionForm responsabili della memorizzazione dei valori del modulo. Possiamo portare la gestione dei moduli a un livello superiore. Nell'applicazione strutspersonne1, abbiamo creato una classe PersonneDynaForm per convalidare i valori del modulo (nome, età). In pratica, alcune convalide si verificano frequentemente: campo non vuoto, campo che convalida una specifica espressione regolare, campo intero, campo data, ecc. Questo tipo di convalida standard può quindi essere specificato nel file di configurazione struts-config.html. Se tutte le convalide da eseguire sono "standard", non è necessario scrivere una classe per il modulo. Questo è ciò che esamineremo ora.