Le
Action base standard di Struts
Struts fornisce alcune Action base che arricchiscono il framework
di alcune funzionalità rispetto alla Action base standard
e che sono utili a diversi scopi . Di seguito forniamo una
descrizione di quelle più utilizzate nella pratica.
La
DispatchAction
Abbiamo già visto precedentemente che nel funzionamento
standard di Struts , il framework esegue il metodo execute()
della Action che corrisponde al URL della richiesta effettuata
dal client. Il metodo execute() costituisce quindi il punto
di ingresso nel framework a fronte di una richiesta dal client.
Questo funzionamento si adatta poco alle situazioni nelle
quali è necessario eseguire una serie di elaborazioni
tra loro logicamente collegate. Tipico è l'esempio
di operazioni di inserimento, cancellazione , lettura e aggiornamento
su una stessa tabella di un database. Sarebbe abbastanza poco
efficiente dover definire una Action per ciascuna singola
operazione , in quanto questa tecnica porterebbe ad un proliferare
di Action nell'applicazione e quindi ad una difficile gestione
della stessa. Struts ci viene incontro fornendo org.apache.struts.actions.DispatchAction.
La DispatchAction è assolutamente analoga ad una Acion
base ma fornisce la possibilità di invocare diversi
metodi della stessa purchè il client specifichi il
metodo da chiamare. In pratica è come una Action che
non ha un solo metodo execute() ma ne ha n con nomi diversi.
Ognuno di questi metodi deve avere la stessa signature del
metodo execute().
Ad esempio una DispatchAction potrebbe avere i seguenti metodi:
public
ActionForward inserisci(ActionMapping mapping, ActionForm
form,
HttpServletRequest
req, HttpServletResponse res)
throws
IOException,ServletException;
public
ActionForward aggiorna(ActionMapping
mapping, ActionForm form,
HttpServletRequest
req, HttpServletResponse res)
throws
IOException,ServletException;
public
ActionForward cancella(ActionMapping
mapping, ActionForm form,
HttpServletRequest
req, HttpServletResponse res)
throws
IOException,ServletException;
public
ActionForward leggi(ActionMapping
mapping, ActionForm form,
HttpServletRequest
req, HttpServletResponse res)
throws
IOException,ServletException;
Affinché
il framework sappia a quale metodo delegare l'elaborazione
della richiesta, il client deve fornire nella request un parametro
contenente il nome del metodo corrispondente. Questo parametro
va ovviamente specificato nella definizione della Action nello
struts-config.xml nel seguente modo:
<action
path="/gestioneTabella"
type="it.esempio.GestioneTabellaAction"
name="gestioneTabellaForm"
scope="request"
input="/tabella.jsp"
parameter="metodo"/>
Se
quindi da una pagina JSP si vuole invocare il metodo inserisci()
della Action GestioneTabellaAction sarà sufficiente
specificare:
http://servername/context-root/gestioneTabella?metodo=inserisci
Chiaramente
il nome del metodo può essere specificato in diversi
modi, come un hidden contenuto in un form HTML oppure può
essere impostato da una funzione JavaScript prima di eseguire
la submit() del form.
L'importante è che è possibile raggruppare logicamente
azioni tra di loro correlate in un'unica Action il che porta
ad una migliore strutturazione dell'applicazione ed evita
duplicazioni inutili di codice. Nella pratica comune la DispatchAction
è effettivamente molto utile e a mio parere salvo eccezioni
è quella da utilizzare come classe base per le Action
della propria applicazione invece della semplice Action standard.
La
LookupDispatchAction
La org.apache.struts.actions.LookupDiapatchAction è
utile quando la scelta del metodo da eseguire in una Action
di tipo 'dispatch' è effettuata mediante i button di
un form ma si ha la necessità di avere le label dei
button localizzate e non ci si vuole affidare a codice JavaScript
per la selezione del metodo da attivare.
La LookupDiapatchAction è quindi del tutto analoga
alla DispatchAction per quel che riguarda la sua struttura,
quello che cambia è il modo con il quale viene selezionato
il metodo da mandare in esecuzione.
In questo caso le label dei button vengono asscociate alle
loro key contenute nel resource bundle dell'applicazione,
e queste key, che molto probabilmente non sono nomi di metodo
validi, vengono mappate dallo sviluppatore ai metodi della
Action mediante la definizione di un metodo così fatto:
protected
Map getKeyMethodMap(ActionMapping mapping, ActionForm form,
HttpServletRequest request) {
Map map = new HashMap();
map.put("bottone.leggi", "leggi");
map.put("bottone.inserisci", "inserisci");
map.put("bottone.cacnella", "cancella");
map.put("bottone.modifica", "modifica");
return map;
}
Nel
metodo viene definita una HashMap nella quale ad ogni key
è associato il nome di un metodo della Action. Questo
metodo è usato dal framework per determinare la corrispondenza
tra la label localizzata del bottone cliccato ed il metodo
della LookupDispatchAction da eseguire.
In base a questo codice la definizione dei bottoni nella pagina
JSP sarà del seguente tipo:
<html:form
action="/gestioneTabella">
<html:submit property="method">
<bean:message key=" bottone.leggi ">
</html:submit>
<html:submit property="method">
<bean:message key=" bottone.inserisci ">
</html:submit>
<html:submit property="method">
<bean:message key=" bottone.cacnella ">
</html:submit>
<html:submit property="method">
<bean:message key=" bottone.modifica ">
</html:submit>
</html:form>
In questo modo è possibile avere una Action di tipo
'dispatch' i cui metodi sono attivabili da button di un form
di una applicazione localizzata semplicemente scrivendo un
metodo getKeyMethodMap() come descritto.
La
BaseAction
La org.apache.scaffold.http.BaseAction è una Action
fornita nei package opzionali denominati Scaffold. E' una
Action che fornisce un metodo execute() base fatto come segue:
public
ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest
req, HttpServletResponse res)
throws
Exception {
//
Controlla le pre-condizioni all'elaborazione
preProcess(mapping,form,request,response);
// ci sono errori va in failure
if (isErrors(request)) {
return findFailure(mapping,form,request,response);
}
//
Esecuzione della logica
try {
executeLogic(mapping,form,request,response);
}
catch (Exception e) {
//
Gestione dell'eccezione
setException(request,e);
catchException(mapping,form,request,response);
}
finally {
// Elaborazioni finali
postProcess(mapping,form,request,response);
}
//
Se ci sono errori va in failure
if (isErrors(request)) {
return findFailure(mapping,form,request,response);
}
//
Otherwise, check for messages and succeed (only 1_0)
if ((isStruts_1_0()) && (isMessages(request)))
{
saveErrors(request,getMessages(request,false));
}
}
La
BaseAction può essere usata come classe base di tutte
le Action dell'applicazione allo scopo di standardizzare la
scrittura dei vari metodi execute(). In pratica in questo
caso lo sviluppatore dovrà implementare nella propria
Action il metodo executeLogic() ed eventualmente uno tra i
metodi preProcess() o postProcess(). Il metodo execute() della
ActionBase rispecchia le operazioni effettuate in genere da
un comune metodo execute() di una Action. Questo approccio
può essere comunque usato come spunto per costruirsi
una propria Action base se non si vuole utilizzare la BaseAction
dei package Scaffold.
Le
Action standard di Struts per il controllo del flusso
Struts fornisce alcune standard che consentono di controllare
il flusso elaborativo.
La
ForwardAction
La ForwardAction consente di inoltrare il flusso dell'applicazione
ad un'altra risorsa individuata mediante un URI valido, risorsa
che può essere una pagina JSP una servlet o altro.
La ForwardAction quindi non fa altro che creare un RequestDispatcher
ed effettuare il forward alla risorsa individuata dall'attributo
parameter specificato nella definizione della Action nello
struts-config.xml.
<action
path="/vaiAllaPagina1"
type="org.apache.struts.actions.ForwardAction"
name="pagina1Form"
scope="request"
input="/pagina0.jsp"
parameter="/pagina1.jsp "/>
La
ForwardAction è molto utile quando nell'applicazione
si hanno pagine JSP che non richiedono alcuna elaborazione
a monte prima di essere visualizzate. Affinché si eviti
di effettuare un inoltro alla pagina in questione direttamente
da un'altra pagina JSP dell'applicazione si può usare
la ForwardAction. In questo modo si resta aderenti al modello
di Struts che prevede un controllo centralizzato di tutte
le richieste e si predispone l'applicazione a modifiche future.
Se un domani infatti la pagina in questione richiedesse invece
qualche elaborazione basterà sostituire una Action
opportuna al mapping precedentemente corrispondente alla ForwardAction.
Un altro utilizzo della ForwardAction è come elemento
di integrazione con altre applicazioni data la sua caratteristica
di effettuare un inoltro ad un URI generico.
La
IncludeAction
La IncludeAction è la corrispettiva della ForwardAction
per l'operazione di include della risposta generata da un'altra
risorsa. Consente di aggiungere alla propria elaborazione
l'elaborazione effettuata da un'altra risorsa quale ad esempio
una servlet. Non è molto utilizzata ma è comunque
fornita da Struts qualora potesse servire.
Conclusioni
In questo articolo abbiamo esaminato alcune Action fornite
da Struts e molto usate nella pratica comune. Sicuramente
la DispatchAction è quella maggiormente usata e più
utile ai fini di una corretta strutturazione della propria
applicazione. In progetti reali è molto facile che
le Action della propria applicazione estendano la DispatchAction
piuttosto che la Action standard, anche se poi il funzionamento
alla base delle due è esattamente lo stesso.
Bibliografia
[1] Chuck Cavaness - "Programming Jakarta Struts",
O'Reilly, 2003
[2] James Goodwill, Richard Hightower - "Professional
Jakarta Struts" - Wrox 2004
[3] Richard Hightower - "Jakarta Struts Live" -
SourceBeat 2004
Alfredo
Larotonda, laureato in Ingegneria Elettronica, lavora
da diversi anni nel settore IT. Dal 1999 si occupa di Java
ed in particolare dello sviluppo di applicazioni web J2EE.
Dopo diverse esperienze di disegno e sviluppo ora si occupa
in particolare di aspetti architetturali per progetti rivolti
al mercato finanziario ed industriale. E' in possesso delle
certificazioni SCJP (Sun Certified Java Programmer), SCWCD
(Sun Certified Web Component Developer) e SCBCD (Sun Certified
Business Component Developer).
|