Struts2 è un framework per applicazioni web diffuso e maturo basato sul modello di progettazione MVC. Struts2 non è solo la prossima versione di Struts 1, ma è una riscrittura completa dell'architettura di Struts.

Ecco alcune delle fantastiche funzionalità che potrebbero costringerti a considerare Struts2:

  • POJO forms and POJO actions- Struts2 ha eliminato gli Action Forms che erano parte integrante del framework Struts. Con Struts2, puoi utilizzare qualsiasi POJO per ricevere l'input del modulo. Allo stesso modo, ora puoi vedere qualsiasi POJO come una classe Action.

  • Tag support - Struts2 ha migliorato i tag del modulo e i nuovi tag consentono agli sviluppatori di scrivere meno codice.

  • AJAX support - Struts2 ha riconosciuto il subentro delle tecnologie Web2.0 e ha integrato il supporto AJAX nel prodotto creando tag AJAX, che funzionano in modo molto simile ai tag standard Struts2.

  • Easy Integration - L'integrazione con altri framework come Spring, Tiles e SiteMesh è ora più semplice con una varietà di integrazioni disponibili con Struts2.

  • Template Support - Supporto per la generazione di visualizzazioni utilizzando modelli.

  • Plugin Support- Il comportamento principale di Struts2 può essere migliorato e potenziato mediante l'uso di plugin. Sono disponibili numerosi plugin per Struts2.

Il pattern Model-View-Controller in Struts2 è realizzato con i seguenti cinque componenti principali:

  • Actions

  • Interceptors

  • Stack di valori / OGNL

  • Risultati / Tipi di risultati

  • Visualizza le tecnologie

Di seguito è riportato il ciclo di vita di una richiesta nell'applicazione Struct2:

  • L'utente invia una richiesta al server per richiedere alcune risorse (es. Pagine).

  • FilterDispatcher esamina la richiesta e quindi determina l'azione appropriata.

  • Si applicano le funzionalità degli intercettori configurati come convalida, caricamento di file ecc.

  • L'azione selezionata viene eseguita per eseguire l'operazione richiesta.

  • Anche in questo caso, gli intercettori configurati vengono applicati per eseguire qualsiasi post-elaborazione, se necessario.

  • Infine il risultato viene preparato dalla vista e restituisce il risultato all'utente.

Il file struts.xml contiene le informazioni di configurazione che verranno modificate durante lo sviluppo delle azioni. Questo file può essere utilizzato per sovrascrivere le impostazioni predefinite per un'applicazione, ad esempio struts.devMode = false e altre impostazioni definite nel file delle proprietà. Questo file può essere creato nella cartella WEB-INF / classes.

Il tag costante insieme agli attributi name e value verrà utilizzato per sovrascrivere una qualsiasi delle seguenti proprietà definite in default.properties, come abbiamo appena impostato la proprietà struts.devMode. L'impostazione della proprietà struts.devMode ci consente di vedere più messaggi di debug nel file di registro.

Definiamo tag di azione che corrispondono a ogni URL a cui vogliamo accedere e definiamo una classe con il metodo execute () a cui si accederà ogni volta che accediamo all'URL corrispondente.

I risultati determinano cosa viene restituito al browser dopo l'esecuzione di un'azione. La stringa restituita dall'azione dovrebbe essere il nome di un risultato. I risultati vengono configurati per azione come sopra o come risultato "globale", disponibile per ogni azione in un pacchetto. I risultati hanno attributi di nome e tipo facoltativi. Il valore del nome predefinito è "successo".

Il file di configurazione struts-config.xml è un collegamento tra i componenti Visualizza e Modello nel client Web.

Qui è dove si associa la sottoclasse ActionForm a un nome. Utilizzi questo nome come alias per il tuo ActionForm nel resto del file struts-config.xml e anche nelle tue pagine JSP.

Questa sezione mappa una pagina della tua webapp su un nome. È possibile utilizzare questo nome per fare riferimento alla pagina effettiva. Ciò evita la codifica degli URL nelle tue pagine web.

Qui è dove si dichiarano i gestori di moduli e sono noti anche come mapping di azioni.

Questa sezione indica a Struts dove trovare i file delle proprietà, che contengono richieste e messaggi di errore.

Questo file di configurazione fornisce un meccanismo per modificare il comportamento predefinito del framework. In realtà tutte le proprietà contenute nel file di configurazione struts.properties possono essere configurate anche nel web.xml utilizzando il parametro init, oltre che utilizzando il tag costante nel file di configurazione struts.xml. Ma se ti piace mantenere le cose separate e più specifiche, puoi creare questo file nella cartella WEB-INF / classes. I valori configurati in questo file sovrascriveranno i valori predefiniti configurati in default.properties contenuto nella distribuzione struts2-core-xyzjar.

Gli intercettatori sono concettualmente gli stessi dei filtri servlet o della classe proxy JDK. Gli intercettatori consentono di implementare funzionalità trasversali separatamente dall'azione e dal framework. È possibile ottenere quanto segue utilizzando gli intercettori:

  • Fornire la logica di pre-elaborazione prima che l'azione venga chiamata.

  • Fornire la logica di postelaborazione dopo che l'azione è stata chiamata.

  • Cattura delle eccezioni in modo che sia possibile eseguire un'elaborazione alternativa.

Creare un intercettore personalizzato è facile; l'interfaccia che deve essere estesa è l'interfaccia Interceptor.

L'azione effettiva verrà eseguita utilizzando l'interceptor dalla chiamata invocation.invoke (). Quindi puoi eseguire una pre-elaborazione e una post-elaborazione in base alle tue esigenze.

Il framework stesso avvia il processo effettuando la prima chiamata a invoke () dell'oggetto ActionInvocation. Ogni volta che invoke () viene chiamato, ActionInvocation consulta il suo stato ed esegue qualunque intercettore venga dopo. Quando tutti gli intercettori configurati sono stati invocati, il metodo invoke () farà eseguire l'azione stessa.

La classe Action gestisce lo stato dell'applicazione e il tipo di risultato gestisce la visualizzazione.

Il tipo di risultato predefinito è dispatcher, utilizzato per l'invio alle pagine JSP.

Il tipo di risultato del dispatcher è il tipo predefinito e viene utilizzato se non viene specificato alcun altro tipo di risultato. Viene utilizzato per inoltrare a un servlet, JSP, pagina HTML e così via sul server. Utilizza il metodo RequestDispatcher.forward ().

Il tipo di risultato di reindirizzamento chiama il metodo response.sendRedirect () standard, facendo in modo che il browser crei una nuova richiesta nella posizione specificata. Possiamo fornire la posizione sia nel corpo dell'elemento <risultato ...> che come elemento <param name = "location">.

Lo stack di valori è un insieme di diversi oggetti che mantiene i seguenti oggetti nell'ordine fornito:

  • Temporary Objects- Ci sono vari oggetti temporanei che vengono creati durante l'esecuzione di una pagina. Ad esempio, il valore di iterazione corrente per una raccolta di cui viene eseguito il looping in un tag JSP.

  • The Model Object - Se si utilizzano oggetti del modello nella propria applicazione Struts, l'oggetto del modello corrente viene posizionato prima dell'azione nella pila dei valori.

  • The Action Object - Questo sarà l'oggetto azione corrente che viene eseguito.

  • Named Objects - Questi oggetti includono #application, #session, #request, #attr e #parameters e fanno riferimento agli ambiti servlet corrispondenti.

L'Object-Graph Navigation Language (OGNL) è un potente linguaggio di espressione che viene utilizzato per fare riferimento e manipolare i dati su ValueStack. OGNL aiuta anche nel trasferimento dei dati e nella conversione del tipo.

La mappa ActionContext è composta da quanto segue:

  • application - variabili nell'ambito dell'applicazione.

  • session - variabili con ambito di sessione.

  • root / value stack - tutte le tue variabili di azione sono memorizzate qui.

  • request - richiesta di variabili con ambito.

  • parameters - parametri di richiesta.

  • atributes - gli attributi memorizzati in pagina, richiesta, sessione e ambito dell'applicazione.

Il caricamento di file in Struts è possibile tramite un intercettore predefinito chiamato FileUpload interceptor, disponibile tramite la classe org.apache.struts2.interceptor.FileUploadInterceptor e incluso come parte di defaultStack.

Di seguito sono riportate le proprietà di configurazione di Struts2 che controllano il processo di caricamento dei file:

  • struts.multipart.maxSize- La dimensione massima (in byte) di un file da accettare come caricamento di file. L'impostazione predefinita è 250 M.

  • struts.multipart.parser- La libreria utilizzata per caricare il modulo multiparte. Per impostazione predefinita è jakarta.

  • struts.multipart.saveDir- La posizione in cui memorizzare il file temporaneo. Per impostazione predefinita è javax.servlet.context.tempdir.

L'intercettatore fileUplaod utilizza diversi tasti di messaggio di errore predefiniti:

  • struts.messages.error.uploading - Un errore generale che si verifica quando il file non può essere caricato.

  • struts.messages.error.file.too.large - Si verifica quando il file caricato è troppo grande come specificato da maximumSize.

  • struts.messages.error.content.type.not.allowed - Si verifica quando il file caricato non corrisponde ai tipi di contenuto previsti specificati.

È possibile sovrascrivere il testo di questi messaggi nei file di risorse WebContent / WEB-INF / classes / messages.properties.

Al centro di Struts, abbiamo il framework di convalida che aiuta l'applicazione a eseguire le regole per eseguire la convalida prima che il metodo di azione venga eseguito. La classe Action dovrebbe estendere la classe ActionSupport, al fine di ottenere il metodo di convalida eseguito.

Quando l'utente preme il pulsante di invio, Struts 2 eseguirà automaticamente il metodo validate e se una qualsiasi delle istruzioni if ​​elencate all'interno del metodo è vera, Struts 2 chiamerà il suo metodo addFieldError. Se sono stati aggiunti errori, Struts 2 non procederà a chiamare il metodo di esecuzione. Piuttosto, il framework Struts 2 restituirà un input come risultato del richiamo dell'azione.

Quindi, quando la convalida fallisce e Struts 2 restituisce l'input, il framework Struts 2 visualizzerà nuovamente il file di visualizzazione. Poiché abbiamo utilizzato i tag del modulo di Struts 2, Struts 2 aggiungerà automaticamente i messaggi di errore appena sopra il modulo archiviato.

Questi messaggi di errore sono quelli che abbiamo specificato nella chiamata al metodo addFieldError. Il metodo addFieldError accetta due argomenti. Il primo è il nome del campo del modulo a cui si applica l'errore e il secondo è il messaggio di errore da visualizzare sopra quel campo del modulo.

Il secondo metodo per eseguire la convalida consiste nel posizionare un file xml accanto alla classe di azione. La convalida basata su XML di Struts2 fornisce più opzioni di convalida come la convalida della posta elettronica, la convalida dell'intervallo intero, il campo di convalida del modulo, la convalida dell'espressione, la convalida dell'espressione regolare, la convalida richiesta, la convalida della stringa obbligatoria, la convalida della lunghezza della stringa e così via.

Il file xml deve essere denominato "[action-class]" - validation.xml.

Di seguito è riportato l'elenco dei vari tipi di convalida a livello di campo e non di campo disponibili in Struts2:

  • validatore di data

  • doppio validatore

  • validatore email

  • validatore di espressioni

  • validatore int

  • validatore di espressioni regolari

  • validatore richiesto

  • validatore di stringa richiesta

  • validatore stringlength

  • validatore di URL

L'internazionalizzazione (i18n) è il processo di pianificazione e implementazione di prodotti e servizi in modo che possano essere facilmente adattati a lingue e culture locali specifiche, un processo chiamato localizzazione. Il processo di internazionalizzazione è talvolta chiamato traduzione o abilitazione della localizzazione.

Struts2 fornisce la localizzazione, ad es. supporto per l'internazionalizzazione (i18n) tramite bundle di risorse, intercettori e librerie di tag nei seguenti luoghi:

  • I tag dell'interfaccia utente.

  • Messaggi ed errori.

  • All'interno delle classi di azione.

Il formato di denominazione più semplice per un file di risorse è:

bundlename_language_country.properties

Qui bundlename potrebbe essere ActionClass, Interface, SuperClass, Model, Package, Global resource properties. La parte successiva language_country rappresenta la locale del paese, ad esempio la locale spagnola (Spagna) è rappresentata da es_ES e la locale inglese (Stati Uniti) è rappresentata da en_US ecc. Qui puoi saltare la parte del paese che è facoltativa.

Quando si fa riferimento a un elemento del messaggio tramite la sua chiave, il framework Struts cerca un pacchetto di messaggi corrispondente nel seguente ordine:

  • ActionClass.properties

  • Interface.properties

  • SuperClass.properties

  • model.properties

  • package.properties

  • struts.properties

  • global.properties

La classe StrutsTypeConverter dice a Struts come convertire l'ambiente in una stringa e viceversa sovrascrivendo due metodi convertFromString () e convertToString ().

Struts 2 viene fornito con tre temi integrati:

  • simple theme- Un tema minimale senza "campane e fischietti". Ad esempio, il tag textfield esegue il rendering del tag HTML <input /> senza etichetta, convalida, segnalazione degli errori o qualsiasi altra formattazione o funzionalità.

  • xhtml theme - Questo è il tema predefinito utilizzato da Struts 2 e fornisce tutte le nozioni di base fornite dal tema semplice e aggiunge diverse funzionalità come il layout della tabella a due colonne standard per l'HTML, le etichette per ciascuno degli HTML, la convalida e la segnalazione degli errori ecc.

  • css_xhtml theme - Questo tema fornisce tutte le nozioni di base fornite dal tema semplice e aggiunge diverse funzionalità come il layout standard basato su CSS a due colonne, utilizzando <div> per i tag HTML Struts, le etichette per ciascuno dei tag HTML Struts, posizionati secondo il CSS foglio di stile.

Struts semplifica la gestione delle eccezioni mediante l'uso dell'intercettore "eccezioni". L'intercettore "eccezioni" è incluso come parte dello stack predefinito, quindi non devi fare nulla in più per configurarlo. È disponibile out-of-the-box pronto per l'uso.

Un'annotazione @Results è una raccolta di risultati. Sotto l'annotazione @Results, possiamo avere più annotazioni @Result.

@Results({
   @Result(name = "success", value = "/success.jsp"),
   @Result(name = "error", value = "/error.jsp")
})
public class Employee extends ActionSupport{
 ...
}

Le annotazioni @result hanno il nome che corrisponde al risultato del metodo di esecuzione. Contengono anche una posizione su quale vista dovrebbe essere servita corrispondente al valore restituito da execute ().

@Result(name = "success", value = "/success.jsp")
public class Employee extends ActionSupport{
 ...
}

Viene utilizzato per decorare il metodo execute (). Il metodo Action accetta anche un valore che è l'URL su cui viene richiamata l'azione.

public class Employee extends ActionSupport{
   private String name;
   private int age;
   @Action(value = "/empinfo")
   public String execute() {
      return SUCCESS;
   }
}

L'annotazione @After contrassegna un metodo di azione che deve essere chiamato dopo che il metodo di azione principale e il risultato è stato eseguito. Il valore restituito viene ignorato.

public class Employee extends ActionSupport{
   @After
   public void isValid() throws ValidationException {
      // validate model object, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

L'annotazione @Before contrassegna un metodo di azione che deve essere chiamato prima che il metodo di azione principale e il risultato siano stati eseguiti. Il valore restituito viene ignorato.

public class Employee extends ActionSupport{
   @Before
   public void isAuthorized() throws AuthenticationException {
      // authorize request, throw exception if failed
   }
   public String execute() {
      // perform secure action
      return SUCCESS;
   }
}

L'annotazione @BeforeResult contrassegna un metodo di azione che deve essere eseguito prima del risultato. Il valore restituito viene ignorato.

public class Employee extends ActionSupport{
   @BeforeResult
   public void isValid() throws ValidationException {
    // validate model object, throw exception if failed
   }
   public String execute() {
      // perform action
      return SUCCESS;
   }
}

Questa annotazione di convalida controlla se ci sono errori di conversione per un campo e li applica se esistono.

public class Employee extends ActionSupport{
   @ConversionErrorFieldValidator(message = "Default message", 
                        key = "i18n.key", shortCircuit = true)
   public String getName() {
       return name;
   }
}

Questa annotazione di convalida controlla che un campo data abbia un valore all'interno di un intervallo specificato.

public class Employee extends ActionSupport{
   @DateRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "2005/01/01", max = "2005/12/31")
   public String getDOB() {
       return dob;
   }
}

Questa annotazione di convalida controlla che un doppio campo abbia un valore all'interno di un intervallo specificato. Se non è impostato né min né max, non verrà eseguito nulla.

public class Employee extends ActionSupport{
   @DoubleRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   minInclusive = "0.123", maxInclusive = "99.987")
   public String getIncome() {
       return income;
   }
}

Questa annotazione di convalida controlla che un campo sia un indirizzo e-mail valido se contiene una stringa non vuota.

public class Employee extends ActionSupport{
   @EmailValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getEmail() {
       return email;
   }
}

Questo validatore di livello non di campo convalida un'espressione regolare fornita.

@ExpressionValidator(message = "Default message", key = "i18n.key", 
shortCircuit = true, expression = "an OGNL expression" )

Questa annotazione di convalida controlla che un campo numerico abbia un valore all'interno di un intervallo specificato. Se non è impostato né min né max, non verrà eseguito nulla.

public class Employee extends ActionSupport{
   @IntRangeFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   min = "0", max = "42")
   public String getAge() {
       return age;
   }
}

Questa annotazione convalida un campo stringa utilizzando un'espressione regolare.

@RegexFieldValidator( key = "regex.field", expression = "yourregexp")

Questa annotazione di convalida controlla che un campo non sia nullo. L'annotazione deve essere applicata a livello di metodo.

public class Employee extends ActionSupport{
   @RequiredFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getAge() {
       return age;
   }
}

Questa annotazione di convalida controlla che un campo String non sia vuoto (cioè non nullo con una lunghezza> 0).

public class Employee extends ActionSupport{
   @RequiredStringValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, trim = true)
   public String getName() {
       return name;
   }
}

Questo validatore controlla che un campo String sia della lunghezza giusta. Si presuppone che il campo sia una stringa. Se non è impostato né minLength né maxLength, non verrà eseguito nulla.

public class Employee extends ActionSupport{
   @StringLengthFieldValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true, 
   trim = true, minLength = "5",  maxLength = "12")
   public String getName() {
       return name;
   }
}

Questo validatore controlla che un campo sia un URL valido.

public class Employee extends ActionSupport{
   @UrlValidator(message = "Default message", 
   key = "i18n.key", shortCircuit = true)
   public String getURL() {
       return url;
   }
}

Se desideri utilizzare più annotazioni dello stesso tipo, queste annotazioni devono essere nidificate all'interno dell'annotazione @Validations ().

public class Employee extends ActionSupport{
  @Validations(
   requiredFields =
      {@RequiredFieldValidator(type = ValidatorType.SIMPLE, 
      fieldName = "customfield", 
      message = "You must enter a value for field.")},
   requiredStrings =
      {@RequiredStringValidator(type = ValidatorType.SIMPLE, 
      fieldName = "stringisrequired", 
      message = "You must enter a value for string.")}
   )
   public String getName() {
       return name;
   }
}

Questa annotazione può essere utilizzata per i validatori personalizzati. Utilizza l'annotazione ValidationParameter per fornire parametri aggiuntivi.

@CustomValidator(type ="customValidatorName", fieldName = "myField")

Questa è un'annotazione indicatore per le conversioni di tipo a livello di tipo. L'annotazione di conversione deve essere applicata a livello di tipo.

@Conversion()
   public class ConversionAction implements Action {
}

Questa annotazione imposta CreateIfNull per la conversione del tipo. L'annotazione CreateIfNull deve essere applicata a livello di campo o di metodo.

@CreateIfNull( value = true )
private List<User> users;

Questa annotazione imposta l'elemento per la conversione del tipo. L'annotazione dell'elemento deve essere applicata a livello di campo o di metodo.

@Element( value = com.acme.User )
private List<User> userList;

Questa annotazione imposta la chiave per la conversione del tipo. L'annotazione chiave deve essere applicata a livello di campo o di metodo.

@Key( value = java.lang.Long.class )
private Map<Long, User> userMap;

Questa annotazione imposta KeyProperty per la conversione del tipo. L'annotazione KeyProperty deve essere applicata a livello di campo o metodo.

@KeyProperty( value = "userName" )
protected List<User> users = null;

Questa annotazione di annotazione viene utilizzata per le regole di conversione a livello di applicazione e di classe. L'annotazione TypeConversion può essere applicata a livello di proprietà e metodo.

@TypeConversion(rule = ConversionRule.COLLECTION, 
converter = "java.util.String")
public void setUsers( List users ) {
   this.users = users;
}