HTML Guida Struts
HTML Guida 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.
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.
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
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.
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).
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)
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 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.
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.
Per effettuare prove o verifiche è ecco un esempio completo di web.xml (img/xeb.xml.html) per
un'applicazione Struts.
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>
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="...">
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">
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>
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" />
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">
<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.
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.
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.
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
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.
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
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()
<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.*;
System.out.println("REMOVE USER!!!!");
return mapping.findForward("success");
}
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.*;
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">
<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!!
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 {
//...
<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">
</action-mappings>
</struts-config>
<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>
<html>
<body>success!!</body>
</html>
ApplicationResources_en_US.properties
userForm.save=Save
userForm.remove=Remove
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>
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>
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.
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.*;
31
private String username = null;
private String 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>
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>
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">
<action path="/removeMappingDispatchUserSubmit"
type="fulvios.UserMappingDispatchAction"
parameter="remove">
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);
}
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
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;
}
public EsempioRequestProcessor() { }
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;
}
}
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>
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;
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 {
try {
// Carica le proprietà
properties.load(fis);
// ...
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>
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>
38
nella libreria Html.
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" %>
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.
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>
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
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