Il 0% ha trovato utile questo documento (0 voti)
3K visualizzazioni

HTML Guida Struts

Caricato da

Andrea MAestri
Copyright
© Attribution Non-Commercial (BY-NC)
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
3K visualizzazioni

HTML Guida Struts

Caricato da

Andrea MAestri
Copyright
© Attribution Non-Commercial (BY-NC)
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 42

Guida Apache Struts

1
Indice generale
Introduzione.....................................................................................................................................4
Perché usare Struts...........................................................................................................................4
Il design pattern MVC.....................................................................................................................4
Componenti e gestione delle richieste in Struts...............................................................................5
Il ciclo di vita delle richieste............................................................................................................6
Creare un progetto Struts con Eclipse..............................................................................................7
Struttura di una semplice applicazione............................................................................................7
Il deployment descriptor per Struts..................................................................................................9
Configurare la ActionServlet.........................................................................................................10
Il mapping delle servlet..................................................................................................................11
La taglib.........................................................................................................................................11
Pagina di benvenuto ed errori........................................................................................................11
Il file di configurazione 'struts-config.xml'....................................................................................11
global-forwards..............................................................................................................................12
form-beans.....................................................................................................................................13
action-mappings.............................................................................................................................13
message-resources.........................................................................................................................14
plug-in............................................................................................................................................14
File di configurazione multipli......................................................................................................15
Hello World con Struts...................................................................................................................15
Regole e consigli per scrivere applicazioni con Struts..................................................................17
Processo di sviluppo......................................................................................................................18
Scrivere il markup solo nelle viste.................................................................................................18
Tutte le Action finiscono con il .do................................................................................................18
Sui jar.............................................................................................................................................18
Test e configurazione.....................................................................................................................19
ActionServlet.................................................................................................................................19
La classe ActionServlet e il RequestProcessor..............................................................................19
Configurare l'ActionServlet...........................................................................................................20
Le Action........................................................................................................................................21
Creare una Action..........................................................................................................................21
Il metodo execute()........................................................................................................................22
Azioni HTTP e Custom.............................................................................................................22
ActionForward...............................................................................................................................22
Configurazione della classe Action................................................................................................23
DispatchAction..............................................................................................................................24
LookupDispatchAction..................................................................................................................26
Forward Action..............................................................................................................................29
Esempio.........................................................................................................................................29
Link a forward globali...................................................................................................................30
Forward Attribute vs. ForwardAction............................................................................................31
Forward per accesso Legacy..........................................................................................................31
MappingDispatchAction e altre Action già pronte........................................................................33
MappingDispatchAction................................................................................................................33
BaseAction.....................................................................................................................................34
IncludeAction.................................................................................................................................34
Il RequestProcessor........................................................................................................................34
I Plugin...........................................................................................................................................36

2
init()...............................................................................................................................................36
destroy().........................................................................................................................................36
Creare un Plugin............................................................................................................................37
Le taglib di struts...........................................................................................................................38
Jsp Custom Tag..............................................................................................................................38
Utilizzare una taglib.......................................................................................................................39
La HTML taglib.............................................................................................................................39
Tag generici per la formattazione e la navigazione.......................................................................39
Il tag <html:html>.....................................................................................................................40
Tag per i form................................................................................................................................40
Il tag <html:form>.....................................................................................................................40
Gli eventi JavaScript......................................................................................................................41
Bean taglib e gestione dei messaggi..............................................................................................41
Bean taglib e gestione dei messaggi...................................................................................................41
Il tag <bean:message>: la gestione dei messaggi..........................................................................41

3
Introduzione

Apache Struts è un progetto open source sponsorizzato dalla Apache Software Foundation ed è
un'implementazione Java server-side del design pattern MVC (Model View Controller).
Il progetto Struts è nato con l'intenzione di implementare un framework open-source per la
creazione di applicazioni Web che permettesse la separazione del livello di presentazione e che
fosse, allo stesso tempo, astratto dai vari livelli di dati e dalle transazioni.
Nato nel 2000 per opera di Craig R. McClanahan (http://blogs.sun.com/craigmcc/), la popolarità del
framework è cresciuta enormemente nel corso degli ultimi anni. Dopo il rilascio di Struts 1.1, nel
giugno 2003, Struts è diventato uno degli scenari più importanti per lo sviluppo di complesse
applicazioni web basate su JSP.
Nel 2008 nasce Struts 2, che si differenzia parecchio dalla prima versione: questa release non
segue infatti il progetto originale, ma è una evoluzione di WebWork
(http://www.opensymphony.com/webwork/), il framework open source, parte del progetto
OpenSymphony. Per questo motivo la migrazione tra la versione 1 e la versione 2 non è semplice.
In questa guida ci occuperemo della versione 1 del progetto e analizzeremo la versione 2 per
differenze con la prima.

Perché usare Struts


Questo framework semplifica notevolmente la vita di un programmatore, sia in fase di sviluppo, che
di revisione e di configurazione delle proprie applicazioni.
L'utilizzo di Struts supporta vantaggi significativi in termini del progetto:
• Modularità e Riusabilità: i diversi ruoli dell'applicazione sono affidati a diversi
componenti. Ció consente di sviluppare codice modulare e più facilmente riutilizzabile
• Manutenibilità: l'applicazione è costituita da livelli logici ben distinti. Una modifica in uno
dei livelli non comporta modifiche negli altri
• Rapidità di sviluppo: è possibile sviluppare in parallelo le varie parti dell'applicazione,
logica di business e di view

Il design pattern MVC


Iniziamo esaminando le 3 componenti alla base del design pattern MVC:
Componente Descrizione
Rappresenta i dati, tipicamente persistenti su database, attraverso oggetti, questa
Model rappresentazione ci permette di manipolare e il modello dei dati in modo
semplificato
È lo strato più esterno, quello di presentazione. È qui che definiamo l'interfaccia
View utente, forniamo una rappresentazione del modello dei dati e riceviamo richieste
dall'esterno.
È il componente che contiene la logica di business. Qui gestiamo le interazioni con
Controller l'interfaccia, istradiamo le richieste, preleviamo i dati dal Model e stabiliamo quale
View dovrà rappresentarli e come.
Figura 1. Model View Controller

4
Questo approccio si preoccupa di separare la responsabilità nelle web application. Una richiesta
client viene intercettata dal Controller, attraverso il Model vengono forniti tutti i metodi per
accedere ai dati dell'applicazione e quindi per elaborare la risposta e visualizzarla attraverso i
componenti View.
Il componente più importante è quindi il Controller ed è la parte fondamentale del framework.
La potenza di questo sistema sta, infatti, nella possibilità di scegliere diverse tecnologie per
implementare le classi del Model (dal più comune dei DAO a ORM di vario genere come Hibernate
(http://java.html.it/articoli/leggi/2421/introduzione-ad-hibernate/)) e il View Engine che si
preferisce (JSP, Velocity, etc.).
Nel corso della guida analizzeremo i principali componenti di un'applicazione basata su Struts
suddividendoli in componenti model, view e controller; poi passeremo alla configurazione di un
applicazione web, descriveremo le funzionalità più importanti offerte da questo framework e infine
analizzeremo i concetti principali della nuova versione del progetto.

Componenti e gestione delle richieste in Struts

Struts, come ogni application framework, è un insieme di classi e interfacce che costituiscono lo
scheletro per costruire le nostre Web application. In questa lezione iniziamo ad esaminare i
componenti fondamentali e il ciclo di vita delle richieste.
Componente Descrizione
È la servlet di controllo che gestisce tutte le richieste dell'applicazione. Come
tutte le servlet estende la classe javax.servlet.http.HttppServlet e
ActionServlet
quindi implementa tutti i metodi di lifecycle, incluso init(), doGet(),
doPost() ed il destroy
È il cuore di tutta l'applicazione. In questo file XML possiamo definire i vari
struts-config.xml elementi dell'applicazione e le loro associazioni. Viene letto in fase di start-up
dell'applicazione dalla ActionServlet
Le Action sono le classi alle quali le ActionServlet delegal'elaborazione della
Action
richiesta
Contiene gli oggetti associati ad una Action nello struts-config come ad esempio
ActionMapping
gli ActionForward
Sono considerati dei veri contenitori di dati. Fanno riferimento ad uno specifico
ActionForm form e vengono popolati automaticamente dal framework con i dati contenuti
nella request HTTP
ActionForward Contengono i path ai quali la servlet di Struts inoltra il flusso in base alla logica

5
dell'applicazione
Sono tag particolari forniti dal framework Struts per assolvere a molti dei più
Custom-tags
comuni compiti delle pagine JSP

Il ciclo di vita delle richieste


Vediamo questi componenti all'opera, esaminando il flusso elaborativo che viene innescato in Struts
da una richiesta. Per farlo ci serviamo di un semplice schema:
Figura 1. Flusso Elaborativo di Struts

Come abbiamo detto il controller ha la responsabilità di ricevere l'input da un client, invocare le


operazioni necessarie alla logica applicativa e coordinare la vista da restituire al client. In altre
parole contiene tutte la logica di business.
Il componente Model fornisce gli oggetti necessari alla logica di business per astrarre la persistenza
dei dati. Infine le view rappresentano il modo di interagire dell'applicazione con l'utente sia in fase
di richiesta che in fase di risposta.
• I dati per la configurazione sono stati letti dallo struts-config.xml in fase di startup(0
)

• il Client invia una richiesta HTTP(1)


• la richiesta quale viene ricevuta dalla servlet di Struts che provvede a popolare l'ActionForm
associato alla richiesta con i dati della request(2) e l'ActionMapping associata alla richiesta(4)
• L'Action Servlet delega l'elaborazione dati alla relativa Action(3) passandole in input gli
oggetti con request e response HTTP, l'ActionForm e l'ActionMapping precedentemente
valorizzati
• La Action compie la logica di business e rende permanente lo stato dell'applicazione
colloquiando con il Model(5)
• Al termine dell'elaborazione restituisce alla ActionServlet un ActionForward(6) contenente il
path della vista da fornire all'utente
• La Action esegue il forward alla vista specifica nell'ActionForward(7)

6
Questo flusso di operazioni non è completo e in prima battuta sembra un po' confusionario, ma ci
sarà utile come mappa, per avere presenti gli attori che vengono coinvolti nella elaborazione delle
richieste in un'applicazione.

Creare un progetto Struts con Eclipse

Nelle prime lezioni abbiamo fornito una visone d'insieme del framework, che ci sarà utile per
approfondire i concetti nel corso della guida. In questa lezione iniziamo a prendere confidenza con
l'infrastruttura di Struts e ci cimentiamo con un primo, semplice, progetto.
Prima di iniziare con la configurazione della nostra prima applicazione, è utile ricordare che
esistono due filoni di sviluppo del framework corrispondenti alle versioni 1 e 2 Struts. Tratteremo
delle differenze tra le due versioni in seguito, per ora concentriamoci sulla prima, che sarà
argomento predominante della guida. Per prima cosa quindi scarichiamo l'ultima release di Struts 1
(http://struts.apache.org/download.cgi#struts1310).
Figura 2. Download della versione 1.3.10

Struts è distribuito sia sotto forma di codice sorgente (source), sia tramite i "file binari" (full
distribution). Scaricare il codice sorgente garantisce un maggior controllo sull'ambiente in cui si
effettua la compilazione, ma non è adatto ai principianti. Se non si hanno particolari esigenze (come
la modifica o l'inclusione di una classe java nella propria installazione), si può tranquillamente usare
la distribuzione binaria.
Per i nostri esempi utilizziamo la "distribuzione binaria". Possiamo quindi cliccare sul link sotto
Full Distribution.
Una volta estratto l'archivio, troviamo diverse cartelle. Il framework è composto da circa 300
classi Java, divise in otto package principali (il numero delle classi è approssimativo perché il
framework subisce di continuo aggiunte e aggiustamenti).

Struttura di una semplice applicazione


Per esaminare la struttura delle cartelle di una semplice applicazione Struts possiamo servirci dei

7
file .war di esempio che troviamo nella cartella apps dell'archivio estratto.
Questi esempi risultano parecchio interessanti soprattutto per chi inizia. Infatti, per entrare nella
logica di Struts e applicare il ciclo di vita delle richieste, che abbiamo mostrato nella lezione
precedente, è utile esaminare la struttura delle cartelle di un progetto.
Per farlo abbiamo diverse possibilità: possiamo ad esempio rinominare il file struts-blank-
1.x.x.war in ProvaStruts.war ed effettuare il deploy su un container come Tomcat o
JBoss.
Una alternativa ancora più semplice è quella di utilizzare un tool come Eclipse per effettuare le
nostre prove e, siccome siamo nell'ambito di applicazioni JEE, scarichiamo Eclipse per sviluppatori
JEE (http://www.eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/galileor)
Possiamo importare il progetto in Eclipse da menu File -> Import e scegliendo il formato
Web
Figura 3. Importare il file .war in Eclipse

Ogni applicazione Web J2EE al di sotto della cartella in cui viene installata (ad esempio webapp di
Tomcat) rispetta una struttura simile a quella che troviamo anche nel nostro progetto su Eclipse:
WebContent (da considerarsi la 'root' dell'applicazione)
|
+-- WEB-INF
| |
| +-- src (contiene il codice delle nostre servlet)
| |
| +-- classes
| |
| +-- lib (qui ci sono le librerie del framework Struts)
| |
| +-- tags
|
+-- META-INF
|
+-- pages (contiene le JSP per le viste)

Figura 4. Struttura delle cartelle

8
Alcuni di questi contenitori come WEB-INF sono fissi, ma possiamo personalizzare le altre
directory modificando il file di configurazione della nostra applicazione. Ricapitolando:
• WebContent è la root dell'applicazione. Qui possiamo inserire le nostre pagine dinamiche
(le viste JSP) organizzate in cartelle e tutta la parte statica del sito come le pagine HTML, i
fogli di stile e le immagini.
• WEB-INF contiene i sorgenti delle azioni e i file di configurazione xml
• lib contiene le librerie del framework e gli altri JAR utili all'applicazione. In generale,
quando non abbiamo uno strumento automatico a farlo per noi, dobbiamo copiare la cartella
lib che troviamo nell'archivio di Struts all'interno della nostra applicazione
• classes: una cartella contenente le classi compilate dell'applicazione organizzate in cartelle
corrispondenti alla struttura dei package

Il deployment descriptor per Struts

Il web.xml è il descrittore di deploy usato per configurare qualsiasi Web application sviluppata
con tecnologia J2EE (http://java.html.it/guide/leggi/136/guida-j2ee/), quindi anche un'applicazione
Struts avrà il suo descrittore. In più, per la configurazione di una applicazione Struts, abbiamo
bisogno di un secondo file, parimenti importante: lo struts-config.xml.
In questa lezione però analizziamo i passi necessari a scrivere un web.xml per Struts, mentre
approfondiremo lo struts-config.xml nella prossima lezione.
Il file web.xml contiene le informazioni di configurazione necessarie all'application server, per
caricare i componenti necessari all'avvio dell'applicazione.
Questo file serve infatti a descrivere tutti i componenti dell'applicazione Web, contiene informazioni
come:
• Parametri ed inizializzazione ServletContext
• Contenuto localizzato
• Configurazione della sessione
• Definizione Servlet/JSP
• Mapping Servlet/JSP
• Riferimenti a tag library
• Mappature a tipi MIME
• Lista di file di Welcome
• Pagine di errore
• Informazioni sulla sicurezza

9
Se lo apriamo con un tool come Eclipse, riusciamo ad esaminarne meglio le aree principali:
Figura 5. Web.xml su Eclipse

Una curiosità interessante: Eclipse mette in verdino, vicino ad ogni tag, i tag children previsti dal
suo XML Schema.
Sebbene oggi gli ambienti di sviluppo provvedano alla compilazione automatica di questo file, è
sempre bene conoscerne la struttura. Perciò possiamo provare a creare un file web.xml per la
nostra applicazione, a partire da uno vuoto:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application
2.3//EN" "http://java.sun.com/dtd/web app_2_3.dtd">

<web-app>

</web-app>

Configurare la ActionServlet
Il primo passo, uno dei più importanti, consiste nel configurare la ActionServlet che si occuperà di
ricevere e smistare tutte le richieste dell'applicazione (il nostro controller). Quindi provvediamo a
configurare l'istanza della servlet nel seguente modo:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>

10
È importante notare che abbiamo associato alla servlet il file di configurazione (struts-
config.xml), che, in questo modo, sarà caricato all'avvio dell'applicazione.

Il mapping delle servlet


Il passo successivo, necessario a configurare la servlet controller di Struts nel web.xml, lo
compiamo scrivendo il "mapping delle servlet". Utilizziamo l'elemento <servlet-mapping>
nel seguente modo:
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

In altre parole abbiamo detto all'application server di girare tutte le richieste che hanno il suffisso
.do, alla servlet ActionServlet.

La taglib
Struts mette a disposizione dei tag JSP e per utilizzarli dobbiamo dichiarane l'uso all'avvio
dell'applicazione. Per farlo elenchiamo le librerie di tag nel web.xml, grazie all'elemento
<taglib>:
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>

In questo caso abbiamo dichiarato la libreria struts-html ma come vedremo più avanti non è
l'unica messa a disposizione da Struts.

Pagina di benvenuto ed errori


Infine nel deployment descriptor, anche se non vale per le applicazioni che usano Struts, può essere
gestita la pagina di benvenuto dell'applicazione:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

e gli errori HTTP, inserendo i relativi codici (404, 500, etc.):


<error-page>
<error-code>404.jsp</error-code>
<location>404.jsp</location>
</error-page>

Per effettuare prove o verifiche è ecco un esempio completo di web.xml (img/xeb.xml.html) per
un'applicazione Struts.

Il file di configurazione 'struts-config.xml'

11
Per caricare e creare all'avvio tutti i componenti necessari all'applicazione, Struts fa riferimento ad
un file di configurazione chiamato struts-config.xml. Questo file ci permette di specificare
in maniera dichiarativa il comportamento dei componenti del framework, evitando che le
informazioni e il comportamento siano inseriti rigidamente nel codice delle applicazioni.
Questo fornisce agli sviluppatori la flessibilità necessaria ad inserire le proprie estensioni, che il
framework può utilizzare in maniera dinamica.
Lo stuts-config si basa sul formato XML e può essere validato con il DTD di Struts, analizziamone
la struttura.
Il tag root dello struts-config è <struts-config>, all'interno del quale troviamo cinque sezioni:
• global-forwards
• form-beans
• action-mappings
• message-resources
• plug-in
In questa lezione le presentiamo brevemente, ma ce ne occuperemo più approfonditamente nel
corso della guida.

global-forwards
In questa sezione possiamo creare delle associazioni tra particolari nomi (che specificano azioni del
controller) e i relativi percorsi (che specificano delle viste), stabilendo dei forward validi a livello
"globale" nell'applicazione.
In altre parole non si fa altro che mappare le condizioni di ritorno di una richiesta con particolari
Jsp. Lo facciamo utilizzando un elemento <forward> per ogni associazione, grazie alle proprietà
name e path.
Un esempio può essere dato da una pagina globale per gli errori, scrivendo una entry nel global-
fowards in questo modo:
<global-forwards>
<forward name="error" path="/error.jsp"/>
</global-forwards>

Grazie a questa configurazione, quando in caso di errore viene richiamata l'action error,
l'applicazione inoltra la richiesta dell'utente alla Jsp con path /error.jsp.
Analizziamo gli attributi più importanti per configurare un global-forward:
Attributo Descrizione
Serve a dichiarare la classe che estende il bean di configurazione e che manterrà
className tutte le informazioni di forward. Se non specificata, la classe predefinita sarà
org.apache.struts.action.ForwardConfig
È il nome (unico) che servirà a riferirsi a questo forward nell'applicazione. Questo
Name
attributo è obbligatorio
È l'URI verso cui dovrebbe avvenire il forward. È un attributo obbligatorio e deve
path
cominciare con il carattere "/"

12
form-beans
La seconda parte serve a definire i form bean, particolari classi che contengono i dati inseriti in un
form all'interno di una Jsp. Si dichiara uno o più form bean nel seguente modo:
<form-beans>
<form-bean name="..." type="..." />
</form-beans>

Ecco gli attributi più importanti per configurare un form bean:


Attributo Descrizione
Quando non si vuole utilizzare il bean di configurazione standard di Struts, bisogna
className
specificare in questo attributo la classe creata nell'applicazione che la sostituisce
È il nome (unico) che servirà a riferirsi a questo form bean in tutta l'applicazione.
Name
Questo attributo è obbligatorio
Type Il nome di una classe Java che estende la classe ActionForm di Struts
Analizzeremo meglio la struttura e le tipologie dei form bean nei capitoli successivi.

action-mappings
In questa sezione definiamo le action. Per ogni azione inseriamo un elemento <action> e ne
specifichiamo sia le caratteristiche (grazie alle proprietà come path, name, parameters, etc.)
sia i forward dell'azione stessa (grazie ad elementi <forward>). Ecco come pùo presentarsi la
dichiarazione di una action:
<action-mappings>
<action path="/..." name="..." scope="..." type="..."
parameter="..." validate="...">

<forward name="..." path="/..." />


</action>
</action-mappings>

Analizziamo gli attributi più importanti per definire un action-mapping:


Attributo Descrizione Necessità
È il percorso per la request inviata. Deve iniziare con il
path carattere "/" e senza l'estensione del nome del file. In altre obbligatorio
parole è il nome dell'azione
name È il nome del form bean associato all'azione facoltativo
Il path per il modulo di immissione dati verso il quale deve obbligatorio se è
input essere reindirizzato il controllo se si verifica un errore di specificato
validazione l'attributo name
Valore booleano (false o true) che indica se il metodo
validate validate() del form bean, deve essere invocato prima di facoltativo
eseguire l'action, per default è true
Indica quale visibilità abbia il form bean e assumere i valori
scope request (relativo solamente alla sola richiesta) o session facoltativo
(relativo per tutta la sessione dell'utente)
Forward Questo elemento ci permette di indicare il nome (attributo facoltativo, può non

13
essere dichiarato se
name) e il path (attributo path) di una servlet o di una pagina
presenti gli attributi
JSP verso cui verrà effettuato il forward
type o include.
È usato per elaborare la request se gli attributi forward o facoltativo ed
include non sono specificati. Si deve dichiarare il nome di esclusivo rispetto a
type
una classe Java che estende la forward e
org.apache.struts.action.Action include
facoltativo ed
Indica il path di una servlet o di una pagina JSP che saranno
include esclusivo rispetto a
incluse nella response
forward e type
Serve a dichiarare il nome di un attributo necessario ad facoltativo e ha
attribute accedere al form bean dell'action da dichiarare (vedremo precedenza rispetto
meglio questo meccanismo in seguito) all'attributo name
È utilizzato per passare informazioni extra all'istanza
dell'action selezionata. All'interno della action, possiamo
parameter facoltativo
recuperare un parametro definito in questo modo grazie al
metodo getParameter()
Serve ad indicare una classe alternativa per il mapping e la
className configurazione dell'action. Di default Struts usa facoltativo
org.apache.struts.ActionMapping
Ecco un esempio di action mapping, in cui associamo il path "/azione" alla classe
it.html.struts.MyAction, indichiamo che utilizzeremo il form myForm e che per gli
errori ci serviamo della vista dataerror.jsp:
<action path = "/azione"
type = "it.html.struts.MyAction"
name = "myForm"
input = "/WEB-INF/jsp/dataError.jsp">

<forward name="OK" path="/WEB-INF/jsp/viewResult.jsp"/>


<forward name="ERROR" path="/WEB-INF/jsp/busError.jsp"/>
</action>

message-resources
I message-resources, sono classi utili per gestire i messaggi in modo unificato
nell'applicazione. Sono particolarmente utili per applicazioni multilingua.
<message-resources parameter="MessageResources" />

Vedremo che nelle viste si farà riferimento a delle chiavi (key) che saranno poi associate ai
messaggi corrispondenti.

plug-in
Infine abbiamo la parte dedicate alla dichiarazione dei plugin usati nell'applicazione. Osserviamo
come aggiungere alla nostra applicazione uno dei plugin più utilizzati del framework, il validator
che permette di validare i parametri inseriti in un form:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">

14
<set-property property="pathnames"
value="/org/apache/struts/validator/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>

File di configurazione multipli


Nei progetti di grandi dimensioni è possibile specificare più di un file di configurazione. Ciò
consente, ad esempio, l'importazione di componenti specifici per particolari rami dell'applicazione,
o di avere più applicazioni Struts sullo stesso server.
Per dichiarare un nuovo ramo dell'applicazione, ad esempio la sezione blog, dobbiamo agire sul
web.xml ed aggiungere un parametro all'elemento <servlet>
<init-param>
<param-name>config/blog</param-name>
<param-value>/WEB-INF/struts-blog-config.xml</param-value>
</init-param>

Hello World con Struts

In questa lezione vediamo come su possa realizzare una applicazione di benvenuto (la classica
"Hello World"), che visualizza un messaggio di benvenuto. Iniziamo ad approfondire alcuni concetti
e ne lasceremo altri da trattare in seguito.
Dopo aver creato il nostro progetto J2EE con Eclipse importiamo il file struts-blank-
1.x.x.war così come abbiamo visto nella lezione precedente
(http://java.html.it/guide/lezione/4556/creare-un-progetto-struts-con-eclipse/). Ecco ciò che
otteniamo lanciando l'applicazione (per esempio su TomCat):
Figura 6. Risultato dell'applicazione

In precedenza abbiamo visto come questo progettino rappresenti l'ossatura di base di una
applicazione Struts. In questa lezione continueremo ad analizzare i file di questa applicazione, per
comprenderne il funzionamento.
I componenti principali dell'applicazione struts-blank sono:

15
• Il file WEB-INF/web.xml
• Il file WEB-INF/struts-config.xml
• I file .jsp (index.jsp, pages/Welcome.jsp)
• Il file WEB-INF/classes/message.properties
• Le api di Struts contenute nella cartella WEB-INF/lib
Il file web.xml come abbiamo detto nelle lezioni precedenti, non è un file di Struts ma il file di
configurazione per ogni applicazione J2EE.
Apriamo il file e osserviamo il contenuto degli elementi <servlet> e <servlet-mapping>:
è sovrapponibile alla configurazione standard già esaminata in precedenza:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

index.jsp

Infatti anche qui troviamo la configurazione dell'ActionServlet e la sua mappatura, con la delega
alla classe ActionServlet di gestire tutti i file che abbiano estensione .do. Infine definiamo
come file di partenza la vista index.jsp.
Esaminiamo quindi il file configurazione WEB-INF/struts-config.xml.
<global-forwards>
<forward name="welcome" path="/Welcome.do"/>
</global-forwards>

Nel global-forwards diciamo che quando viene inviata una richiesta alla pagina
/Welcome.do, questa viene associata ad un forward di nome welcome
<action-mappings>
<action path="/Welcome" forward="/pages/Welcome.jsp"/>
</action-mappings>

Questa dicitura serve per configurare l'action Welcome.do definendone il forward alla pagina
/pages/Welcome.jsp. Inoltre abbiamo la dichiarazione del message-resource:
<message-resources parameter="MessageResources" />

Lo struts-config della nostra piccola applicazione contiene l'esempio per la configurazione di


qualsiasi componente di Struts.
Adesso passiamo alle due viste. La prima è la index.jsp:
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

16
<logic:redirect forward="welcome"/>

Si dichiara il tag <logic> e si effettua un forward all'action con il nome welcome configurata
nello struts-config.
La pagina pages/welcome.jsp si compone invece nel seguente modo:
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>

<html:html>
<head>
<title><bean:message key="welcome.title"/></title>
<html:base/>
</head>
<body bgcolor="white">

<logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">


<font color="red">
ERROR: Application resources not loaded -- check servlet container
logs for error messages.
</font>
</logic:notPresent>

<h3><bean:message key="welcome.heading"/></h3>
<p><bean:message key="welcome.message"/></p>

</body>
</html:html>

Nelle lezioni successive chiariremo tutte le sue parti, per adesso commentiamo solo queste righe:
<h3><bean:message key="welcome.heading"/></h3>
<p><bean:message key="welcome.message"/></p>

Che servono a prelevare dei messaggi dal "message resource" per comporre la pagina Jsp al
momento della compilazione. Per prelevare i messaggi basta specificare la chiave.
Infine abbiamo il file MessageResources.properties (nella cartella WEB-
INF/src/java/) in cui troviamo le definizioni per tutti i messaggi con le relative chiavi.
welcome.title=Struts Blank Application
welcome.heading=Welcome!
welcome.message=To get started on your own application, copy the struts-
blank.war to a new WAR file using the name for your application. Place it in
your container's "webapp" folder (or equivalent), and let your container auto-
deploy the application. Edit the skeleton configuration files as needed, restart
your container, and you are on your way! (You can find the
MessageResources.properties file with this message in the /WEB-INF/src folder.)

Questo sistema, che permette di associare i messaggi alle chiavi, risulta molto utile, specie quando
vogliamo internazionalizzare l'applicazione.

Regole e consigli per scrivere applicazioni con Struts

Prima di entrare nel dettaglio dei vari componenti di Struts è utile fissare alcune regole che ci

17
aiutino a realizzare applicazioni stabili e revisionabili. Alcune di queste regole hanno carattere
generale: sono valide per Struts ma applicabili anche allo sviluppo con altri framework.

Processo di sviluppo
Struts si basa sul paradigma MVC, ecco un possibile processo di sviluppo di base per tutte le
applicazioni:
1. Disegnare (e poi creare) tutte le viste che rappresentano l'interfaccia utente dell'applicazione
2. Creare e distribuire tutti gli ActionForm (vedremo meglio in seguito di che si tratta)
utilizzati dalle viste
3. Scrivere la logica applicativa realizzando i componenti del Controller
4. Definire le relazioni che esistono tra le Viste e il Controller (struts-config.xml)
5. Apportare le modifiche appropriate al file web.xml
6. Mandare in esecuzione l'applicazione
Abbiamo omesso cose molto importanti come la gestione dei requisiti e l'adozione di una suite per
lo unit testing, ma solo per concentrarci meglio sul framework.

Scrivere il markup solo nelle viste


Un'altra regola impostante per ottenere codice efficiente e per soddisfare i principi del MVC è
quello di scrivere il markup HTML solo nelle nelle viste, quindi nelle pagine Jsp.
Sarebbe infatti possibile rispondere ad una richiesta direttamente dall'Action, sfruttando la funzione
write del componente out. L'oggetto out risulta molto utile soprattutto per accedere ai
parametri e alle proprietà di una sessione, ecco un modo poco ortodosso di utilizzarlo:
out.write("<html><body>Ciao</body></html>");

Questa funzione ci potrebbe "risparmiare la fatica" di creare una pagina Jsp, ma rende le viste non
modificabili e può creare problemi a tutta l'architettura Struts.

Tutte le Action finiscono con il .do


Quando definiamo il controller nel web.xml, dichiariamo una classe di tipo filter, questo
significa che stabiliamo un url-pattern (una espressione) che determina quali richieste
debbano essere gestite dalle nostre Action.
Lo standard di Struts prevede il suffisso .do per le Action, pertanto è buona norma aderire a questa
convenzione, e terminare con il .do tutte le nuove Action che creiamo. Questo è utile soprattutto
per la manutenzione e per non creare confusione nel lavoro di gruppo.

Sui jar
• Non creare package con namespace già presenti in Struts o in altri framework come ad
esempio org.apache.struts.
• Quando si caricano i jar di Struts stare attenti a non avere jar di versioni differenti
• Se si usano altri framework consultare sempre la compatibilità e soprattutto stare attenti a
quando si caricano i jar. In ogni caso Struts è quello di alto livello quindi saranno gli altri
framework a cambiare i jar. È consigliabile creare una nuova cartella e caricare dentro tutti i
jar di struts e degli altri framework così da non avere problemi quando esportiamo

18
l'applicazione.

Test e configurazione
• Per ogni Action o per ogni processo sviluppato è utile testare il funzionamento
dell'applicazione. Infatti con Struts il lavoro di un programmatore consiste soprattutto nella
stesura dei file di configurazione, dove facilmente si può sbagiare qualche percorso, qualche
lettera, etc.
• Lo Struts-config è caricato all'avvio dell'Application Server, quindi se si effettuano
modifiche è necessario ricordare di riavviare l'application Server

ActionServlet

In questo capitolo approfondiamo il Controller, la parte più importante del framework Struts. Il
Controller è composto di i 4 elementi fondamentali, che hanno responsabilità quali ricevere un input
da un client, attivare le operazioni secondo la logica applicativa e gestire le viste e l'interfaccia con
il client.
• la classe ActionServlet
• la classe Action
• i Plugin
• il RequestProcesser

La classe ActionServlet e il RequestProcessor


La classe org.apache.struts.ActionServlet è un elemento fondamentale per le applicazioni Struts.
Si tratta del componente che realizza il Controller nella architettura MVC.
Il suo compito è, infatti, quello di gestire le richieste client e determinare quale
org.apache.struts.action.Action processerà la richiesta arrivata. Funziona come un Action
Factory, creando istanze di classi Action in base alle richieste ricevute.
La ActionServlet è una servlet che, come tutte le altre servlet, estende la classe
javax.servlet.http.HttpServlet e quindi implementa tutti i metodi del ciclo di vita di una servlet
(http://java.html.it/guide/lezione/784/le-servlet/), incluse le attività di init(), doGet(),
doPost() e destroy.
I due punti di ingresso per l'ActionServlet sono essenzialmente gli stessi delle altre servlet:
doGet() e doPost().
// Codice di doGet() e doPost()

public void doGet(HttpServletRequest request, HttpServletResponse response)


throws IOException, ServletException {
process (request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)


throws IOException, ServletException {
process (request, response);
}

19
L'implementazione di questi metodi fa esattamente la stessa cosa, ossia chiamare il metodo
process(). Per capire meglio questo comportamento esaminiamo, passo dopo passo, le attività
compiute dall'ActionServlet quando riceve una richiesta:
1 I metodi doPost() o doGet() ricevono una richiesta e invocano il metodo process()
Il metodo process() ottiene il RequestProcessor corrente e ne invoca a sua volta il
metodo process().
2
Se si intende estendere l'ActionServlet, il posto giusto per la personalizzazione è l'oggetto
RequestProcessor: contiene la logica che il Controller Struts esegue su ogni richiesta
Il metodo RequestProcessor.process() è il luogo dove la richiesta viene
3 effettivamente servita. Questo metodo reperisce, dal file struts-config.xml, l'elemento
<action> che corrisponde al path submitted della richiesta
Quando il metodo RequestProcessor.process() trova una <action> in match, va
4
alla ricerca dell'entry <form-bean> referenziato dall'elemento <action>
Quando il metodo RequestProcessor.process() conosce il "fully qualified name" del
5 FormBean, crea o reperisce un'istanza dell'ActionForm nominato dall'elemento <form-
bean> e popola i membri di istanza con i valori che arrivano dalla richiesta
Quando i dati dell'ActionForm sono stati caricati, il metodo
6 RequestProcessor.process() chiama il metodo ActionForm.validate(), che
controlla la validità dei valori passati
Il metodo RequestProcessor.process() conosce tutto ciò che gli serve e può servire la
7 richiesta. Reperisce il "fully qualified name" della classe Action e chiama il metodo
execute()
Quando la classe azione ritorna dal suo processing, il suo metodo execute() ritorna un
oggetto ActionForward che viene utilizzato per determinare il target della transazione. Il
8
metodo RequestProcessor.process() riacquisisce il controllo e la richiesta viene
indirizzata al target
A questo punto l'ActionServlet ha completato l'elaborazione della richiesta ed è pronto per
servirne delle altre.
Al fine di delgare all'ActionServlet l'unica responsabilità di ricevere e rispondere ad una request
chiamando la giusta Action, dalla versione 1.1 del framework è stata introdotta una nuova classe, il
RequestProcessor (org.apache.struts.action.RequestProcessor), al fine di
elaborare la request per il controller. Grazie a questo disaccoppiamento è possibile personalizzare e
modificare il modo in cui viene elaborata la richiesta.

Configurare l'ActionServlet
Come ogni altra servlet Java, la ActionServlet di Struts deve essere configurata nel
deployment descriptor. Quindi una volta aperto il file web.xml, possiamo inserire le nostre
impostazioni utilizzando l'elemento <servlet>.
Una pratica comune consiste nell'utilizzare l'elemento <load-on-startup> per essere certi che
l'ActionServlet venga avviata quando il container avvia l'applicazione Web.
Ecco un esempio di <servlet> entry che descrive ActionServlet:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

20
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<param-name>debug</param-name>
<param-value>4</param-value>
<init-param></init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Le Action

Le Action sono gli strumenti grazie ai quali il Controller di Struts gestisce le attività. Ogni Action
rappresenta una funzione dell'applicazione, quindi è qui che scriviamo la logica applicativa dei
nostri progetti.
La classe Action disaccoppia le richieste del client dall'applicazione. In altre parole un oggetto di
tipo Action è un'estensione del controller e fa da ponte tra le azioni client-side dell'utente e le
operazioni della logica applicativa.
Ogni Action, come abbiamo già detto (http://java.html.it/guide/lezione/4558/il-file-di-
configurazione-strutsconfigxml/), deve essere dichiarata e configurata nel file struts-
config.xml e non nel web.xml. Il suo nome deve terminare con .do, è questo che permette
alla richiesta di essere processata da Struts e non come una semplice servlet Java.
Le Action servono ad esempio a ricevere le richieste dai form, ad elaborare i dati e a lanciare le
View per la visualizzazione delle informazioni. Per realizzare le Action, è necessario:
• Creare una classe che estenda org.apache.struts.action.Action
• Implementare il metodo execute() aggiungengo la logica di business della nostra
applicazione
• Compilare la nuova Action e spostarla nel classpath dell'applicazione Web
• Aggiungere un elemento <action> al file struts-config.xml all'applicazione che descrive la
nuova azione
Esaminiamo più in dettaglio alcuni di questi passi.

Creare una Action


Dichiarare una nuova Action è molto semplice, è sufficiente estendere la classe base e ricordare di
importare tutti i namespace necessari (se utilizziamo un IDE ci saranno comunque suggeriti):
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class EsempioAction extends Action {

// Qui scriviamo la Action

21
}

Il metodo execute()
La classe base Action ci da l'opportunità e il compito di effettuare l'override del metodo
execute(), riscrivendo questo metodo, possiamo indicare le operazioni che vogliamo far
compiere alla nostra azione. In altre parole è qui che inseriamo la "logica di business".
Il metodo execute() viene invocato dal controller quando viene ricevuta una richiesta. Da non
sottovalutare, per il buon funzionamento dell'applicazione, che una classe Action viene istanziata
una sola volta, all'avvio dell'applicazione, quindi occorre garantire che tutte le Action operino
correttemente in un ambiente multithread, proprio come si fa quando si sviluppa una servlet.
Le funzioni principali di execute() sono:
• compiere la logica dell'applicazione
• instradare la richiesta indicando al Framework il passo successivo da eseguire

Azioni HTTP e Custom


Struts contempla due definizioni per execute().
La prima serve a dichiarare azioni custom che non sono specificatamente HTTP. Questa
implementazione del metodo è analoga alla classe
javax.http.servlet.GenericServlet; e la sua signature è la seguente:
public ActionForward execute(ActionMapping mapping,
ActionForm form,
ServletRequest request,
ServletResponse response
) throws IOException, ServletException

La seconda implementazione viene utilizzata invece per dichiarare azioni HTTP. Ecco la sua
signature:
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response
) throws IOException, ServletException

Campo Descrizione
ActionMapping Contiene le informazioni di deployment per un particolare Action bean
ActionForm Rappresenta gli input del Form contenente i parametri della richiesta
HttpServletRequest È un riferimento all'oggetto HTTP Request
HttpServletResponse È un riferimento all'oggetto HTTP Response
Dopo aver esaminato i parametri passati al metodo execute(), bisogna dare un'occhiata al suo
tipo di ritorno.

ActionForward
Questo oggetto viene utilizzato dal RequestProcessor per determinare la destinazione
successiva della richiesta. Qui si può determinare ad esempio, se sarà lanciata una vista JSP o

22
un'altra azione.
// Esempio di execute()

public class EsempioAction extends Action {

public ActionForward execute(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException,
ServletException
{
if (form!=null) {

// 1. Creazione del form


// (effetuiamo il cast dal form in ingresso)
SkeletonForm actionForm = (SkeletonForm) form;

// 2. Aggiungere qui la Business Logic

// 3. return con un appropriato ActionForward


return mapping.findForward("success");
}
}
}

Nella costruzione delle Action, si segue una procedura comune:


1. effettuare un cast dell'ActionForm referenziato
2. aggiungere la specifica logica di business
3. utilizzare il metodo ActionMapping.findForward() per trovare l'oggetto
ActionForward che effettua un match con il sottoelemento <forward> nella definizione
di <action> (nel file struts-config.xml)
4. restituire l'oggetto ActionForward trovato

Configurazione della classe Action


Le classi Action si configurano nel file struts-config.xml, poiché si tratta di oggetti specifici di
Struts.
L'elemento che viene utilizzato per descrivere un'azione Struts è <action>. e la classe che definisce
gli attributi dell'elemento <action> è org.apache.struts.action.ActionMapping.
<?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>
<!-- qui dichiariamo che il form 'lookupForm' sarà inviato-->
<!-- all'action 'esempio' nel campo ActionForm -->
<form-bean name="lookupForm" type="esempio.LookupForm" />
</form-beans>

<action-mappings>
<!-- la location /Lookup lancerà il nostro form -->

23
<action path="/Lookup" type="esempio.LookupAction" name="lookupForm" >
<!-- le viste da collegare all'esito dell'action -->
<forward name="success" path="/quote.jsp" />
<forward name="failure" path="/index.jsp" />
</action>
</action-mappings>

</struts-config>

Vedremo in seguito come estendere il mapping per definire attributi <action> addizionali.

DispatchAction

Spesso le azioni sembrano essere troppo numerose e troppo piccole, sarebbe utile raggruppare
azioni correlate in una classe facilitando il riutilizzo.
A tale scopo Struts mette a disposizione le DispatchAction
(org.apache.struts.action.DispatchAction). Il principio alla base è che ci possano
essere funzionalità correlate per un servizio che, invece di essere suddivise in molteplici classi
Action, si possono tenere insieme nella medesima classe.
DispatchAction è una classe astratta che estende la classe Action. Anziché avere un singolo metodo
execute, si ha un metodo per ciascuna azione logica.
Nella request, infatti, bisogna inserire un parametro di nome method che sarà usato dalla
DispatchAction per determinare quale metodo invocare.
Per implementare una DispatchAction bisognerà creare:
1. una classe action handler che estenda DispatchAction;
2. un metodo per ciascuna azione logica;
3. un action-mapping per questo action handler
// Un esempio di DispatchAction

import javax.servlet.http.*;
import javax.servlet.*;
import org.apache.struts.actions.*;
import org.apache.struts.action.*;

public class UserDispatchAction extends DispatchAction {

public ActionForward remove(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

System.out.println("REMOVE USER!!!!");
return mapping.findForward("success");
}

public ActionForward save(ActionMapping mapping,


ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

24
System.out.println("SAVE USER!!!!");
return mapping.findForward("success");
}
}

È utile notare che tutti i metodi hanno la stessa firma del metodo Action.execute().
Produciamo il bean che conterrà il valore di method, unica proprietà del form inviante:
// Bean che contiene il valore di method
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class UserForm1 extends ActionForm {

private String method = null;

public String getMethod() { return method; }


public void setMethod(String method) { this.method = method; }

public void reset(ActionMapping mapping, HttpServletRequest request) {


this.method = method;
}
}

Il terzo step è quello per creare un action mapping per questo action handler e aggiungendo un
elemento <form-bean> nel struts-config.xml:
<form-beans>
<form-bean name="userForm1" type="fulvios.UserForm1" />
</form-beans>

<action path="/dispatchUserSubmit"
type="fulvios.UserDispatchAction"
parameter="method"
input="/userForm1.jsp"
name="userForm1"
scope="request"
validate="false">

<forward name="success" path="/success.jsp" />


</action>

Ecco quindi lo step finale: creare la userForm1.jsp.


<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>

<html>
<body>
<html:form action="/dispatchUserSubmit">
action:
<html:select property="method" size="2">
<html:option value="save">Save</html:option>
<html:option value="remove">Remove</html:option>
</html:select>
<br/>
<html:submit/><html:cancel/>
</html:form>

25
<%@ page language="java" %>

success!!

In questo esempio abbiamo la DispachtAction che contiene due metodi remove() e


save(). Questa classe raggruppa tutte le funzionalità a disposizione dell'utente. Se non avessimo
utilizzato una DispachtAction avremmo dovuto creare due Action e implementare i due
metodi excute().
DispacthAction utilizza la reflection per individuare un metodo che corrisponda perfettamente
al nome contenuto nel valore del parametro della richiesta, controllando anche la corrispondenza del
numero e del tipo degli argomenti. Una volta trovato, il metodo sarà invocato e l'oggetto
ActionForward restituito proprio come per una qualunque Action.
Sebbene si tratti di una soluzione valida, è importante utilizzarla con criterio. La
DispatchAction risulta particolarmente utile quando le classi da raggruppare rappresentano
azioni simili tra loro o hanno parti comuni da eseguire prima di effettuare operazioni specifiche. Ad
esempio se dobbiamo prelevare dei dati da un database e modificarli in modo differente a seconda
della scelta di un utente conviene utilizzare una DispatchAction per evitare di scrivere uno
stesso metodo più volte. Inoltre combinando le operazioni, si renderà più semplice la manutenzione
dell'applicazione, infatti se si vuole cambiare l'implementazione di una funzionalità basterà agire
solo su una classe.

LookupDispatchAction

La classe LookupDispatchAction
(org.apache.struts.actions.LookupDispatchAction), è una sottoclasse della
DispatchAction e come quest'ultima ci permette di specificare metodi multipli. Ciascun
metodo poi sarà invocato utilizzando il meccanismo del parametro speciale da inserire nelle
richieste, parametro che viene indicato nel file di configurazione.
Mentre la DispatchAction usa il valore del parametro della request per determinare quale
metodo deve essere invocato, la LookupDispatchAction usa il valore del parametro della
request per effettuare un reverse lookup dal resource bundle usando il valore del parametro e per
farlo corrispondere a un metodo della classe.
In altre parole ci permette di pescare valori dal file delle risorse in modo dinamico.
Per utilizzare LookupDispatchAction è necessario eseguire i seguenti step:
1. Creare un action handler che erediti LookupDispatchAction
2. Creare un metodo che rappresenti ciascuna azione logica
3. Implementare il metodo getKeyMethodMap per mappare le chiavi del file di risorsa ai
nomi dei metodi
4. Creare un action mapping per questo action handler utilizzando l'attributo parameter per
specificare quale parametro conterrà il nome del metodo che si vuole invocare nelle richieste
5. Impostare i messaggi nel resource boundle per le etichette e i valori per i pulsanti
6. Utilizzare bean:message per mostrare le etichette sul pulsante
Il primo step è creare una classe action handler che erediti LookupDispatchAction (codice
completo (http://html.it/guide/img/struts/lookupdispatch_example.html)):

26
// Handler che eredita LookupDispatchAction
public class UserLookupDispatchAction extends LookupDispatchAction {

// È necessario implementare questo metodo che mappi


// le chiavi del file di risorse ai nomi dei metodi
Map getKeyMethodMap() {

Map map = new HashMap();


map.put("userForm.remove", "remove");
map.put("userForm.save", "save");
return map;
}

//...

Questa classe implementa il metodo getKeyMethodMap() che restituisce un oggetto di tipo


java.util.Map contenente una serie di coppie del tipo chiave/valore. Le chiavi di questo Map
dovrebbero corrispondere a quelle del resource bundle, mentre il valore associato dovrebbe essere il
nome del metodo della sottoclasse LookupDispatchAction. Questo valore sarà invocato
quando è incluso un parametro della request corrispondente al messaggio del resource bundle per la
chiave.
Produciamo il bean che conterrà il valore di method, unica proprietà del form inviante:
import javax.servlet.http.*;
import org.apache.struts.action.*;

// Bean che contiene il valore di method

public class UserForm2 extends ActionForm {

private String method = null;

public String getMethod() { return method; }


public void setMethod(String method) { this.method = method; }

public void reset(ActionMapping mapping, HttpServletRequest request) {


this.method = method;
}
}

Creiamo un action mapping (struts-config.xml):


<?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="userForm2" type="simone.UserForm2" />
</form-beans>

<action-mappings>

<action path="/lookupDispatchUserSubmit"
type="simone.UserLookupDispatchAction"
input="/userForm2.jsp"

27
name="userForm2"
parameter="method"
scope="request"
validate="true">

<forward name="success" path="/success.jsp" />


</action>

</action-mappings>
</struts-config>

Scriviamo le nostre viste. Prima il form:


<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

<!-- Form JSP -->

<html>
<body>
<html:form action="/lookupDispatchUserSubmit">
<html:submit property="method">
<bean:message key="userForm.remove" />
</html:submit>

<html:submit property="method">
<bean:message key="userForm.save" />
</html:submit>

<html:cancel></html:cancel>
</html:form>
</body>
</html>

poi la pagina con il risultato:


<%@ page language="java" %>

<!-- JSP con il risultato del form -->

<html>
<body>success!!</body>
</html>

infine il file di risorse, dove impostiamo le etichette e i valori per i pulsanti:


ApplicationResources_it_IT.properties
userForm.save=Salva
userForm.remove=Rimuovi

ApplicationResources_en_US.properties
userForm.save=Save
userForm.remove=Remove

È importante modificare anche il file web.xml a causa dei file di risorse:


<init-param>
<param-name>application</param-name>
<param-value>ApplicationResources</param-value>

28
</init-param>

Si tratta di un percorso piuttosto lungo semplicemente per determinare quale metodo invocare.
L'intento di questa classe è di rendere tutto più facile quando si ha un modulo HTML con pulsanti di
immissione multipli con lo stesso nome.

Forward Action

In genere non è una buona prassi quella di inserire, all'interno di una pagina JSP, dei link diretti ad
altre pagine JSP, soprattutto per questioni di ordine e manutenzione: in effetti è all'interno del file di
configurazione struts-config.xml, che fa parte del Controller, che dovremmo descrivere
l'intero flusso dell'applicazione.
In alcune occasioni possiamo però avere la necessità di effettuare un forward da una pagina Jsp a
un'altra, senza che in realtà ci sia bisogno di passare per una classe Action. Quello che si vuole è un
plain link.
Nell'architettura MVC è compito del controller di elaborare tutte le richieste e selezionare la view
per il client. Se si utilizza un link diretto, a un'altra pagina JSP, si stanno violando i confini
dell'architettura "Model 2" (l'MVC per applicazioni Web).
Se permettessimo alla nostra applicazione di chiamare direttamente la pagina, il controller non
sarebbe in grado di portare a termine i compiti per esso stabiliti nell'architettura MVC. Per risolvere
questi problemi Struts mette a disposizione la ForwardAction che esegue semplicemente un
forward verso un URI configurato nell'attributo parameter dell'action nello struts-config.
Quindi la ForwardAction ci evita la creazione di una classe Action che effettua solamente un
semplice forward.
Prima di esaminare un esempio più consistente vediamo una configurazione tipica di
ForwardAction:
<action input="/index.jsp" path="/provaForward"
parameter="/pagina.jsp"
type="org.apache.struts.actions.ForwardAction">
</action>

Quando viene selezionata l'action /provaForward, viene chiamato l'unico metodo della
ForwardAction, che effettua un forward a pagina.jsp. La classe ForwardAction è
molto utile quando è necessario integrare Struts con altri framework o più pagine Jsp.

Esempio
Abbiamo detto che ForwardAction agisce come bridge tra la vista corrente JSP e la pagina alla
quale si collega. Utilizza il RequestDispatcher per effettuare un forward alla risorsa Web
specificata. È ciò che permette di collegarsi a un'azione invece che direttamente a una pagina
JSP.
Ecco alcuni passi necessari per implementare una ForwardAction:
• utilizzare <html:link> con l'attributo action e aggiungere il link alla pagina JSP che
punta all'azione
• creare un action mapping nel file di configurazione di Struts che utilizza ForwardAction con

29
l'attributo parameter che specifica il percorso alla JSP
Supponiamo di avere una pagina JSP, coded.jsp, che ha un link diretto su un'altra pagina
JSP:
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body>

<html:link page="/index.jsp">Home</html:link>

</body>
</html>

e di volerla convertire secondo la logica dell'architettura MVC/Model2. In questo caso


modifichiamo il tag <html:link>su un'azione. È sufficiente produrre notcoded.jsp:
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body>
<html:link action="home">Home</html:link>
</body>
</html>

Infine bisogna aggiungere un action mapping all'azione home referenziata dal tag html:link:
<action path="/home"
type="org.apache.struts.actions.ForwardAction"
parameter="/index.jsp">
</action>

Link a forward globali


Da una prospettiva di design, c'è un'ulteriore alternativa all'utilizzo dell'azione ForwardAction,
anziché inserire un link a un azione o a una pagina, ci si potrebbe collegare a un global forward.
Ecco un esempio di pagina JSP collegata a un global forward:
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body>
<html:link forward="home">Home</html:link>
</body>
</html>

Per permettere ora al codice di funzionare dobbiamo aggiungere un global forward al file di
configurazione di Struts che mappi l'azione home:
<global-forwards>
<forward name="home" path="/index.jsp" />
</global-forwards>

È possibile anche modificare il global forward in modo che punti a un action mapping:
<global-forwards>
<forward name="home" path="/home.do" />

30
</global-forwards>

Questa, solitamente, è la pratica migliore, infatti, è più naturale collegarsi a forward che ad azioni.

Forward Attribute vs. ForwardAction


Struts permette le due dichiarazioni seguenti nel file struts-config.xml, ma la seconda è
sicuramente più snella:
<!-- ForwardAction -->
<action path="/home"
type="org.apache.struts.actions.ForwardAction"
parameter="/index.jsp" />

<!-- Forward Attribute -->


<action path="/home" forward="/index.jsp" />

Forward per accesso Legacy

Supponiamo di avere una risorsa Web legacy che si vuole utilizzare con la validazione form di
Struts, purtroppo, la risorsa legacy fa parte di un modello MVC elaborato che è stato creato prima
dell'implementazione di Struts.
Per ragioni di semplicità la nostra risorsa legacy sarà una servlet. Essenzialmente si vuole fare in
modo che il metodo doGet di una servlet venga chiamato solo se l'ActionForm valida i dati con
successo. Ecco la nostra servlet d'esempio:
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.*;

import java.io.*;

public class LegacyServlet extends HttpServlet {

public void doGet (HttpServletRequest request, HttpServletResponse response)


throws ServletException, IOException {

ActionMapping mapping = (ActionMapping)


request.getAttribute(Globals.MAPPING_KEY);
UserForm form = (UserForm)request.getAttribute(mapping.getName());
response.getWriter().println("User name: " + form.getUsername() + "
Password: " + form.getPassword());
}
}

e questo è lo UserForm.java, che passa UserName e password


import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;

public class UserForm extends ActionForm {

31
private String username = null;
private String password = null;

public String getUsername() { return username; }


public void setUsername(String username) { this.username = username; }

public String getPassword() { return password; }


public void setPassword(String password) { this.password = password; }

public void reset(ActionMapping mapping, HttpServletRequest request) {


this.username = null;
this.password = null;
}
}

Notiamo che la servlet può accedere al contesto che il Framework di Struts ha mappato su request
(Codice completo del web.xml
(http://html.it/guide/img/struts/legacyforward_webxml_example.html)).
<!-- ... -->
<servlet>
<servlet-name>legacy</servlet-name>
<servlet-class>simone.LegacyServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>legacy</servlet-name>
<url-pattern>/legacy/roar</url-pattern>
</servlet-mapping>

<!-- ... -->

Quindi, un post su /legacy/roar causerebbe l'esecuzione del metodo doGet della servlet.
Ora, per mappare questa servlet su un'azione che agisce come form handler, è necessario mettere
mano a struts-config.xml:
<?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="userForm" type="simone.UserForm" />
</form-beans>

<action-mappings>

<action path="/legacy" forward="/legacy/roar"


input="/userForm.jsp" name="userForm"
parameter="/legacy/roar" validate="true"
scope="request">
</action>
</action-mappings>
</struts-config>

E infine ecco la JSP:


<%@ page language="java" %>

32
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body>
<html: form action="/legacy">
username: <html:text property="username"/><br/>
password: <html:password property="password"/><br/>
<html:submit/><html:cancel />
</html:form>
</body>
</html>

Il RequestDispatcher effettua la chiamata al metodo doGet() della Servlet solo se il


metodo execute() della ForwardAction viene chiamato.
Avendo impostato il metodo validate su true nell'action mapping per la servlet, il metodo
execute() di ForwardAction viene chiamato solo se ActionForm (UserForm)
validates restituisce nessun oggetto ActionError.

MappingDispatchAction e altre Action già pronte

In questa lezione analizzeremo quelle action pronte all'uso, contenute nel package
org.apache.struts.actions, che non abbiamo ancora trattato, ma che vale la pena
conoscere.

MappingDispatchAction
La MappingDispatchAction è identica alla DispatchAction, solo che in fase di mapping
non si specifica più il parametro, ma direttamente il nome del metodo da invocare. La stessa azione
sarà mappata con nomi differenti e sarà chiamata a seconda del metodo da invocare.
Riprendendo l'esempio fatto per la DispatchAction nelle lezioni precedenti, dovremo
modificare innanzitutto l'estensione della classe, che sarà
org.apache.struts.action.MappingDispatchAction. Nello struts-config
scriveremo:
<action path="/saveMappingDispatchUserSubmit"
type=" fulvios.UserMappingDispatchAction"
parameter="save">

<forward name="success" path="/success.jsp" />


</action>

<action path="/removeMappingDispatchUserSubmit"
type="fulvios.UserMappingDispatchAction"
parameter="remove">

<forward name="success" path="/success.jsp" />


</action>

Quindi se vogliamo eseguire il metodo save invocheremo l'azione con il nome


/saveMappingDispatchUserSubmit mentre per il metodo remove
/removeMappingDispatchUserSubmit.

33
BaseAction
La BaseAction è molto simile ad una semplice Action di Struts solo che mette a disposizione
il seguente metodo execute():
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest req, HttpServletResponse res)
throws Exception {

preProcess(mapping,form,request,response);
if (isErrors(request)) {
return findFailure(mapping,form,request,response);
}

try {
executeLogic(mapping,form,request,response);
}
catch (Exception e) {
setException(request,e);
catchException(mapping,form,request,response);
}
finally {
postProcess(mapping,form,request,response);
}

if (isErrors(request)) {
return findFailure(mapping,form,request,response);
}

if ((isStruts_1_0()) && (isMessages(request))) {


saveErrors(request,getMessages(request,false));
}
}

Questo metodo mette a disposizione una parte dove si può implementare una logica di business da
effettuare prima di eseguire il processo vero e proprio che sarà contenuto nel metodo
executeLogic(). Nel metodo è già compresa la gestione delle eccezioni generale.

IncludeAction
La classe IncludeAction ha la stessa funzionalità della ForwardAction solo che permette
l'integrazione di servlet con l'applicazione Struts. Si configura allo stesso modo della
ForwardAction solo che l'attributo parameter deve specificare il path di una servlet, mentre
type deve essere org.apache.struts.actions.IncludeAction.

Il RequestProcessor

Il RequestProcessor è la classe da riscrivere quando si vuole personalizzare il processing


dell'ActionServlet.
Essa contiene un entry point predefinito che viene invocato dal controller di Struts con ciascuna
richiesta. Questo entry point si chiama processPreprocess().

34
Se si desidera aggiungere il proprio processing specializzato al Controller è necessario
implementare il metodo processPreprocess(), aggiungendo la specifica logica e restituendo
true per continuare con il processing normale. Se si desidera terminare il processing normale,
restituire false per dire al controller che la richiesta corrente è completa.
Ecco un esempio di implementazione di default processPreprocess():
protected boolean processPreprocess(HttpServletRequest request,
HttpServletResponse response) {
return true;
}

Per creare il proprio RequestProcessor è necessario seguire gli step seguenti:


• Creare una classe che estende org.apache.struts.action.RequestProcessor;
• Aggiungere un costruttore di default vuoto;
• Implementare il metodo processPreprocess()
Ecco di seguito il codice per creare il RequestProcessor:
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.util.*;
import org.apache.struts.action.RequestProcessor;

public class EsempioRequestProcessor extends RequestProcessor {

public EsempioRequestProcessor() { }

public boolean processPreprocess(HttpServletRequest request,


HttpServletResponse response) {

System.out.println("-------------processPreprocess Logging-------------");
System.out.println("RequestedURI = " + request.getRequestURI());
System.out.println("Protocol = " + request.getProtocol());
System.out.println("Remote Address = " + request.getRemoteAddr());
System.out.println("Remote Host = " + request.getRemoteHost());
System.out.println("Remote User = " + request.getRemoteUser());
System.out.println("Requested Session Id = " +
request.getRequestedSessionId());

return true;
}
}

Nel metodo processPreprocess() reperiamo le informazioni memorizzate in request ed


effettuiamo un log.
Una volta che il log è completato, il metodo processPreprocess ritorna il valore boolean true
e il processing normale prosegue.
Se il metodo processPreprocess avesse restituito false, il Controller avrebbe terminato il normale
processing e l'azione non sarebbe mai stata eseguita.
Per effettuare il deploy del nostro RequestProcessor dobbiamo:
• Compilare il nostro RequestProcessor e metterlo nel classpath dell'applicazione.
• Aggiungere l'elemento <controller> al file di configurazione dell'applicazione struts-

35
config.xml.
Ecco il contenuto totale del file struts-config.xml:
<?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="lookupForm" type="esempio.LookupForm" />
</form-beans>

<action-mappings>
<action path="/Lookup" type="fulvios.LookupAction" name="lookupForm" >
<forward name="success" path="/quote.jsp" />
<forward name="failure" path="/index.jsp" />
</action>
</action-mappings>

<controller processorClass="esempio.EsempioRequestProcessor" />

<plug-in className="esempio.EsempioPlugin" />


</struts-config>

I Plugin

I Plugin di Struts sono estensioni modulari del controller di Struts. Introdotti con Struts 1.1, sono
definiti dall'interfaccia org.apache.struts.action.Plugin. Risultano utili quando si allocano risorse
o si preparano connessioni a database o su risorse JNDI.
Questa interfaccia definisce due metodi init() e destroy(), ovvero i metodi del ciclo di vita
dei Plugin.

init()
Il metodo init() rappresenta l'inizio della vita del plugin: viene invocato quando il container di
JSP/Servlet avvia l'applicazione Web contenente il Plugin. Esaminiamone la firma:
public void init(ActionServlet servlet,
ApplicationConfig applicationConfig
) throws javax.servlet.ServletException;

Quando viene lanciato, il metodo init() riceve un riferimento all'ActionServlet e


all'ApplicationConfig e viene utilizzato per caricare e inizializzare risorse necessarie al
Plugin.
Il riferimento ad ActionServlet permette di referenziare le informazioni del Controller mentre
l'oggetto ApplicationConfig fornisce l'accesso alle informazioni di configurazione che
descrivono l'applicazione Struts.

destroy()
Il metodo destroy() termina la vita del Plugin: viene invocato ogni volta che il container di

36
JSP/Servlet arresta l'applicazione Web contenente il Plugin. Questo metodo risulta molto utile
perché ci sonsente di rilasciare le risorse allocate dal metodo init(). La sua firma è molto
semplice:
public void destroy();

Creare un Plugin
Ecco i passi necessari alla creazione di un Plugin:
• Creare una classe che implementi l'interfaccia
org.apache.struts.action.Plugin
• Aggiungere un costruttore di default vuoto
• Implementare i metodi init() e destroy()
• Compilare il Plugin e spostarlo nel classpath dell'applicazione Web
• Aggiungere l'elemento <plug-in> al file struts-config.xml
Ecco un esempio di plugin (Vedi codice completo (http://www.html.it/articoli/2236/cod01.html)):
public void init(ActionServlet servlet, ModuleConfig applicationConfig) throws
javax.servlet.ServletException {

System.out.println("---->The Plugin is starting<----");


Properties properties = new Properties();

try {

File file = new File("c:/info/startup.info");

// Crea l'input stream


FileInputStream fis = new FileInputStream(file);

// Carica le proprietà
properties.load(fis);

ServletContext context = servlet.getServletContext();

// ...

L'obiettivo di questo Plugin è quello di rendere disponibili un set di proprietà all'avvio


dell'applicazione. Per testarlo non ci resta che:
• Compilare e includere la classe del Plugin nel classpath (spostando il file in una cartella
dell'applicazione, nel nostro caso si chiama esempio)
• Aggiungere l'elemento <plug-in> al file di configurazione struts-config.xml
• Riavviare l'applicazione.
Ecco come appare il file struts-config.xml:
<?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="lookupForm" type="esempio.LookupForm" />
</form-beans>

37
<action-mappings>
<action path="/Lookup" type="esempio.LookupAction" name="lookupForm" >
<forward name="success" path="/quote.jsp" />
<forward name="failure" path="/index.jsp" />
</action>
</action-mappings>

<plug-in className="esempio.EsempioPlugin" />


</struts-config>

Le taglib di struts

Abbiamo già detto che le viste in Struts sono caratterizzate da pagine Jsp. In questo capitolo
esamineremo i vantaggi dell'impiego delle librerie di tag nelle View di Struts. Vedremo i tag più
importanti e le loro funzionalità.
Chi conosce linguaggi di markup come XML (http://xml.html.it/guide/leggi/58/guida-xml-di-base/),
ha già confidenza con il concetto di tag, qui ricordiamo solo la distinzione tra tag "contenitori" e
non.
I tag "senza contenuto" sono quelli che non contengono altri tag, essi specificano l'informazione
servendosi solo degli attributi. Sono spesso impiegati per semplici azioni. Un esempio potrebbe
essere quello delle immagini in HTML:
<img src="percorso-immagine" />

Gli elementi contenitori invece racchiudono altri elementi o un contenuto tra i tag di apertura e
chiusura. L'esempio è quello del paragrafo in HTML:
<p style="text-align:right">Testo allineato a destra</p>

Jsp Custom Tag


Nelle pagine Jsp, oltre al classico markup elaborato direttamente dal browser, è possibile utilizzare
il meccanismo dei Custom Tag, ovvero elementi di markup speciali che vengono interpretati dalla
nostra applicazione e che, ad esempio, servono a generare automaticamente interi pezzi di markup
HTML.
Il rendering e i comportamenti di questi componenti sono affidati ad una specifica classe Java detta
tag handler (http://java.html.it/articoli/leggi/2297/custom-tag-jsp-esempio-di-tag-handler/5/).
L'handler ha accesso a tutte le risorse della Jsp che ospita i componenti (oggetti session,
request, response e pageContext).
Struts mette a disposizione molti tag personalizzati, raggruppati in cinque librerie:
• Html
• Bean
• Logic
• Nested
• Template
Le prime versioni di Struts contenevano anche una sesta libreria di tag chiamata form inclusa poi

38
nella libreria Html.

Utilizzare una taglib


Per usare le taglib bisogna includere il Tag Library Descriptor
(http://java.html.it/articoli/leggi/2297/custom-tag-jsp-definire-un-tag-library-descriptor-tld/3/) (TLD
) per ciascuna libreria, che contiene le definizioni di tutti i tag della libreria.
Possiamo farlo grazie alla direttiva <%@taglib%> che ha questa sintassi:
<%@ taglib uri="/WEB-INF/nome_libreria.tld" prefix="prefisso" %>

Dove con l'attributo uri indichiamo il path del file .tld e con prefix indichiamo all'application
server che dovrà occuparsi di elaborare tutti i tag che iniziano per "prefisso".
Ad esempio, de vogliamo utilizzare le librerie Html e Bean in una pagina Jsp, inseriamo le
seguenti direttive all'inizio della pagina:
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

Possiamo trovare un altro semplice esempio qui (http://java.html.it/articoli/leggi/2297/hello-world-


con-i-custom-tag-di-jsp/2/).
Nelle lezioni successive vedremo nel dettaglio le librerie e i principali tag che li compongono. Per
un riferimento esaustivo su tutti i tag delle librerie di Struts è possibile consultare i javadocs
( http://struts.apache.org/1.x/apidocs/index.html) nella sezione taglib.

La HTML taglib

Una delle librerie di tag più utili di Struts è la HTML taglib: permette di creare form di input e
interfacce utente basate su HTML. Il vantaggio nell'utilizzare questi tag sta nel fatto che
semplificano l'interazione con il framework, grazie ad essi possiamo ragionare direttamente in
termini di action, e concentrarci non tanto sul colloquio tra View e Controller, quanto sulla
realizzazione del front end.
Per importare questi tag dobbiamo inserire il relativo riferimento alle definizioni in testa alla nostra
vista, con una direttiva simile a questa:
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>

In questo caso utilizziamo le definizioni presenti online, ma possiamo anche decidere di utilizzare
definizioni salvate in locale sul nostro server.
Tutti i tag di questa libreria saranno richiamati utilizzando il prefisso html: (ad esempio
<html:link>)
Facciamo un veloce elenco di questi tag, senza scendere nel dettaglio degli attributi: nelle prossime
lezioni esamineremo più dettagliatamente i più importanti.

Tag generici per la formattazione e la navigazione


Nome Funzione

39
html Visualizza un elemento html
Realizza l'elemento base di HTML: definisce in automatico l'indirizzo di base per i link
base
relativi
Crea il codice HTML per il classico link, ma possiamo sfruttarlo per collegare anche le
link
nostre action, che il framework interpreta come ActionForward
img Visualizza un tag HTML img
Definisce un frameset HTML, le pagine vengono chiamate al suo interno con lo stesso
frame
meccanismo del tag <html:link>
errors Serve per mostrare messaggi d'errore, ad esempio in caso di validazione di un form

Il tag <html:html>
È usato per la visualizzazione di un elemento HTML. Permette di includere un attributo locale
che scriverà le impostazioni locali dell'utente. Un esempio di uso di questo tag è per impostare la
lingua dell'applicazione a seconda delle impostazione del browser. Si usa nel seguente modo:
<html:html locale="true">
</html:html>

Tag per i form


Nome Funzione
form Definisce un form HTML
text Casella di testo
password Visualizza un campo di input per le password
textarea Visualizza un campo di input textarea
option Crea un menu a tendina
checkbox Visualizza un campo di input (checkbox)
radio Visualizza un radio button
submit Visualizza un pulsante submit
cancel Crea un campo di input che annulla il form<
reset Visualizza un campo di input con pulsante reset
button Crea un campo di input (pulsante)
Visualizza un campo di input per la selezione di un
file
file
image Visualizza un tag input del tipo image
hidden Genera un campo nascosto
multibox Mostra un elenco di checkbox
options - optionsCollection Visualizza una raccolta di opzioni select

Il tag <html:form>
Il tag <html:form> di Struts è uno dei più importanti della HTML taglib. Permette di
visualizzare un form, che invii i suoi dati riferendosi direttamente ad una action specifica, che potrà
servirsi del relativo ActionForm per memorizzare i dati. Esaminiamone gli attributi più importanti:
Nome Funzione

40
action Deve essere dichiarato l'URL (la action) che riceverà i dati da questo form
method Il metodo HTTP per la richiesta
focus Il nome del campo a cui sarà assegnata la priorità nell'esame della pagina
style Lo stile CSS da applicare al form
Esprime la codifica del contenuto da usare quando questo form viene passato
enctype
all'elaborazione

Gli eventi JavaScript


La maggior parte dei tag HTML supportano i gestori degli eventi Javascript (event handler) tramite
i loro attributi. Sotto l'elenco degli attributi supportati.
Evento Si scatena quando
Onblur l'elemento perde il focus di input
Onclick l'elemento riceve un click del mouse
Onfocus l'elemento riceve il focus
Onkeydown l'elemento ha un focus di input e un tasto è premuto
Onkeypress l'elemento ha un focus di input e un tasto è premuto e rilasciato
onmousemove l'elemento è sotto il puntatore del mouse e il puntatore viene spostato
onmousedown l'emenento viene cliccato

Bean taglib e gestione dei messaggi

Bean taglib e gestione dei messaggi


La Bean taglib è stata creata per permettere alle viste (JSP) di accedere ai JavaBeans e alle proprietà
loro associate. Inoltre, grazie a questi tag possiamo definire nuovi bean accessibili all'interno di una
pagina attraverso variabili di script e attributi con scope di pagina. Ecco un elenco di alcuni di
questi tag:
Tag Descrizione
Cookie Permette l'accesso al valore di uno specifico request cookie
Define Definisce una variabile sulla base del valore di uno specifico bean property
Header Definisce una variabile sulla base del valore di uno specifico request header
Include Permette di includere una pagina generata da un'action o ad un URL esterno
page Espone come bean un oggetto dal contesto della pagina specificata
parameter Permette di accedere al valore di un parametro di richiesta
resource Rende disponibile il valore di una risorsa di una web application

Il tag <bean:message>: la gestione dei messaggi


Il tag <bean:message>, anche se sembra estraneo alle funzionalità della libreria di tag Bean, è
uno dei tag più diffusi di Struts. La sua funzione è quella di prendere un messaggio
internazionalizzato per l'area locale del client tramite la Key del messaggio specificata e lo scrive

41
nell'output. Si usa nel seguente modo:
<bean:message key="..."/>

Alcune librerie di Java permettono il supporto della lettura di risorse di messaggi da una classe Java
o da un file di proprietà. La classe di partenza è la java.util.ResourceBundle. Struts estende questa
funzionalità tramite la org.apache.struts.util.MessagesResources.
Per fissare le idee riprendiamo l'esempio dello struts-blank. La Jsp finale non contiene nessun
messaggio ma solo dei tag bean message con le rispettive key:
<bean:message key="welcome.heading"/>
<bean:message key="welcome.message"/>

I messaggi sono specificati tramite una key nel file message.propeties nel seguente modo:
welcome.heading=Welcome!
welcome.message=To get started on your own application, copy the struts-
blank.war to a new WAR file using the name for your application. Place it in
your container's "webapp" folder (or equivalent), and let your container auto-
deploy the application. Edit the skeleton configuration files as needed, restart
your container, and you are on your way! (You can find the
MessageResources.properties file with this message in the /WEB-INF/src folder.)

Per creare un message resource con struts, basta creare un file .properties nella cartella WEB
INF e dichiarare il nome nello struts-config nel seguente modo:
<message-resources parameter="MessageResources" />

Questa funzionalità oltre a suddividere le varie responsabilità ai singoli componenti, risulta molto
utile quando vogliamo internazionalizzare la nostra applicazione ma di questo ci occuperemo nelle
lezioni successive facendo un esempio.

42

Potrebbero piacerti anche