1. MVC Struts 1
A Web Application Framework
a cura di
Tarin Gamberini
2. Sommario – Parte 1 di 2
1. MVC
1. JSP, JSP Model 1, JSP Model 2
2. Model-View-Controller (MVC) Pattern
3. Distributed Multitiered Applications
4. Dove si inserisce Struts?
www.taringamberini.com MVC Struts 1 2
3. Sommario – Parte 2 di 2
1. Struts 1
1. Installazione e configurazione
2. Controller: Action, ActionForward
3. Model
4. View: ActionForm
5. Struts Custom Tag Library
www.taringamberini.com MVC Struts 1 3
4. MVC
MVC Struts 1
A Web Application Framework
Parte 1 di 2
5. JavaServer Pages (JSP)
Una JSP è un’astrazione (vista ad alto livello) di
una servlet
Il Web Container, a fronte di una Request di una
JSP:
“traduce” il .jsp in un .java (servlet)
compila il .java (servlet) in un .class
Ogni JSP ha molte responsabilità:
view logic, flow logic, data access logic,
business logic, security logic, ...
www.taringamberini.com MVC Struts 1 5
6. JavaServer Pages (JSP)
Parte di logica può essere incapsulata in tag:
Disaccoppiamento fra presentazione (View) e
contenuto (Model)
Una pagina con tag è compresa meglio dai web
designer
Parte di logica rimane nella JSP sotto forma di:
scriptlet <% … String firstDate =
request.getParameter(“firstDate”); … %>
JavaScript per pagine più dinamiche e performanti
<script type=“text/javascript” … validate(firstDate) …
www.taringamberini.com MVC Struts 1 6
8. JSP Model 1
Request e Response sono a carico della JSP
JSP accede alla base dati attraverso JavaBeans:
disaccoppiamento nell’accesso ai dati. Benefici:
La JSP può cambiare (layout) senza obbligare al
cambiamento il JavaBean
Il JavaBean può cambiare (alter table) senza obbligare al
cambiamento la JSP
Architettura adatta per semplici applicazioni:
business logic, data access logic, I18n logic, security
logic, ... sono semplici o del tutto assenti
www.taringamberini.com MVC Struts 1 8
10. JSP Model 2
Request a carico della servlet (Controller),
Response a carico della JSP (View)
Servlet (Controller) ha le responsabilità più
pesanti:
I18n logic, security logic, ...
business logic, persistence logic: istanzia Bean ed
oggetti che userà la JSP
flow logic: in base alle azioni dell’utente determina il
forward alla JSP successiva
JSP (View) ha la responsabilità della
view logic: accede ai Bean istanziati dalla servlet
www.taringamberini.com MVC Struts 1 10
12. MVC Pattern - Scenario
Applicazioni Enterprise supportano più utenti
che utilizzano diverse View, per esempio:
HTML per B2C
WML per B2C
JFC/Swing per amministratori (magazziniere)
XML per B2B
Evitare duplicazione codice View dipendente
(copia/incolla)
Elevati costi di manutenzione
Evoluzione in differenti applicativi, uno per ogni
View, con stesse funzionalità
www.taringamberini.com MVC Struts 1 12
13. MVC Pattern - Obiettivi
Accedere agli stessi dati da presentare in
differenti View: HTML, WML, JFC/Swing, XML
Aggiornare gli stessi dati attraverso interazioni
differenti:
Click sui link di pagina HTML o su WML card
Click sui bottoni di una GUI JFC/Swing
Invio messaggi fra web services SOAP (XML)
Supporto alle diverse View ed ai diversi tipi di
Interazioni utente non deve impattare le core
functionality della enterprise application
www.taringamberini.com MVC Struts 1 13
14. MVC Pattern - Soluzione
Model-View-Controller (MVC) Pattern garantisce
semplificazione delle fasi di sviluppo, test,
manutenzione, attraverso il disaccoppiamento tra core
functionality (M), logica di presentazione (V), logica di
interazione (C)
www.taringamberini.com MVC Struts 1 14
15. MVC Pattern - Model
Il Model è un modello software di
processi che avvengono nel mondo reale
Il Model descrive:
Enterprise data
Regole di accesso/aggiornamento dei dati
Regole di elaborazione dei dati specifiche del
processo modellato (business logic)
www.taringamberini.com MVC Struts 1 15
16. MVC Pattern - View
La View accede ai dati, attraverso il
Model, e li presenta
La View mantiene consistenza fra il dato
presentato ed il dato contenuto nel
Model:
Modalità push (passiva): la View riceve il
dato corrente dal Model
Modalità pull (attiva): la View chiede al
Model il dato corrente (Web application)
www.taringamberini.com MVC Struts 1 16
17. MVC Pattern - Controller
Il Controller traduce le interazioni fra utente e
View in azioni
EventListener per JFC/Swing View
HttpRequest get e post per Web View
Il Controller delega l’esecuzione delle azioni al
Model
Il Controller sceglie la successiva View in
funzione del risultato dell’esecuzione delle
azioni da parte del Model
www.taringamberini.com MVC Struts 1 17
18. Distributed Multitiered Applications
La piattaforma JEE concepisce una
applicazione enterprise secondo un modello
multistrato distribuito
Le funzionalità realizzate dalla logica
applicativa sono divise in componenti installati
in differenti strati e differenti macchine
Client-tier: esegue sulla macchina client
Web-tier: esegue sul JEE server
Business-tier: esegue sul JEE server
EIS-tier (Enterprise Information System): esegue
sul DB server
www.taringamberini.com MVC Struts 1 18
20. Componenti Java EE
Un componente offre una funzionalità
incapsulata in una unità software
Applet e Applicazioni Client: componenti che
eseguono sul client
Java Servlet, JSP, JSF: tecnologie di componenti
web che eseguono sul server
EJB: componenti business che eseguono sul server
Un componente è eseguito su una macchina
all’interno di un Container
www.taringamberini.com MVC Struts 1 20
21. Java EE Containers
I Containers sono un'interfaccia fra i componenti
e le funzionalità, di basso livello, che risiedono
nella piattaforma che supporta tali componenti
EJB Container: componenti (EJB) e container
eseguono sul JEE server
Web Container: componenti (Servlet, JSP) e container
eseguono sul JEE server
Application Container: componenti (applicazioni) e
container eseguono sul client
Applet Container: componenti (Applet) e container
(web browser e Java Plug-in) eseguono sul client
www.taringamberini.com MVC Struts 1 21
22. Java EE Containers
Un componente viene “deployato” nel relativo
Container
www.taringamberini.com MVC Struts 1 22
23. Dove si inserisce Struts?
Struts rappresenta una implementazione del pattern MVC
Struts offre un’infrastruttura su cui costruire una applicazione
enterprise Multi-Tier
www.taringamberini.com MVC Struts 1 23
24. Struts 1
MVC Struts 1
A Web Application Framework
Parte 2 di 2
27. Struts Controller (MVC)
Il Controller (RequestProcessor) traduce le interazioni fra utente e
View in azioni dichiarativamente nello struts-config.xml
<struts-config>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 27
28. Struts Controller (MVC)
Il Controller delega l’esecuzione delle azioni al Model tramite una
classe de gestione dell'azione
<struts-config>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 28
29. Struts Controller (MVC)
Il Controller sceglie la successiva View in funzione del risultato
dell’esecuzione delle azioni da parte del Model
<struts-config>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 29
30. Struts init()
Il Web Container inizializza Struts invocando il metodo
init() della ActionServlet:
1. Lettura delle risorse di messaggi interne di Struts
2. Lettura dal web.xml dei parametri di configurazione di Struts
3. Init. della configurazione:
Parsing dello struts.config.xml (dtd)
Creazione dell'oggetto ApplicationConfig
Salvataggio dell'ApplicationConfig nel ServletContext
4. Init. delle risorse di messaggi
Lettura dei vari message-resources.properties
Salvataggio dei messaggi nel ServletContext
Init. DataSource
Init. Plug-in
www.taringamberini.com MVC Struts 1 30
31. La classe Action
Un Action è il ponte (Adapter) fra il contenuto
di una richiesta HTTP e la logica di business
Estendendo Action si possono progettare
Action personalizzate che delegano
l'elaborazione della richiesta HTTP
all'appropriata logica di business
Il controller di Struts (RequestProcessor)
invoca il metodo execute(...) dell'Action
www.taringamberini.com MVC Struts 1 31
32. La classe Action
public class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response) throws Exception {
// 1. ottiene i parametri dal form
// 2. delega alla logica di business
// 3. determina view successiva
if (...) { return mapping.findForward("success"); }
else { return mapping.findForward("failure"); }
}
}
www.taringamberini.com MVC Struts 1 32
33. Ciclo di vita di una Action
RequestProcessor contiene una HashMap:
Key: nome delle Action nello struts-config.xml
Value: riferimento all'istanza della relativa Action
2. Struts, a fronte di una richiesta di un'Action,
controlla l'HashMap:
Se l'Action non è ancora istanziata (Value==null) la
istanzia, salvandone il riferimento nell'HashMap
Se l'Action era già stata istanziata ne ottiene il
riferimento
Action condivise fra più thread: thread-safe se
progettate senza variabili di istanza
www.taringamberini.com MVC Struts 1 33
34. La classe ActionForward
La classe ActionForward rappresenta una
destinazione alla quale il controller
inoltra il risultato dell'elaborazione della
richiesta HTTP da parte del Business
Una ActionForward può essere:
creato nell'Action
ottenuto dal mapping dichiarato nello struts-
config invocando mapping.findForward(...)
www.taringamberini.com MVC Struts 1 34
35. La classe ActionForward
public class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form, HttpServletRequest request, HttpServletResponse
response) throws Exception {
// 1. ottiene i parametri dal form
// 2. delega alla logica di business
// 3. determina view successiva
if ( ... ) { return mapping.findForward("success"); }
else { return mapping.findForward("failure"); }
}
}
www.taringamberini.com MVC Struts 1 35
36. Struts Model (MVC)
Struts non offre granché per progettare il
Model
Ricorso ad infrastrutture esterne a Struts:
EJB
Progetto di infrastrutture ad-hoc basate su:
JavaBeans (BO, DAO, DTO)
Pattern vari
Object-to-Relational Mapping (iBatis, Hybernate)
www.taringamberini.com MVC Struts 1 36
37. Struts View (MVC)
La View accede ai dati, attraverso il
Model, e li presenta
La presentazione sfrutta un'interfaccia
utente visualizzata dal client all'interno di
un web browser:
HTML, CSS
JSP con JSTL, con Struts custom tag
Resource bundle Java
www.taringamberini.com MVC Struts 1 37
38. Struts View (MVC)
La View mantiene consistenza fra il dato
presentato ed il dato contenuto nel
Model:
Modalità pull (attiva): la View chiede al
Model il dato corrente (il client è un browser
web che inoltra richieste HTTP)
JSP con JSTL, con Struts custom tag
ActionForm di Struts
DTO
www.taringamberini.com MVC Struts 1 38
39. La classe ActionForm
ActionForm è impiegata per catturare i dati in
ingresso da un form HTML e trasferirli alla
classe Action
ActionForm si interpone fra la View ed il
Controller
ActionForm agisce da buffer per i dati del form
HTML mentre sono validati
ActionForm sono JavaBeans: dati del form
HTML memorizzati come properties
www.taringamberini.com MVC Struts 1 39
40. La classe ActionForm
Gli ActionForm sono dichiarati nel file struts-config.xml nella
sezione form-beans:
<struts-config>
<form-beans>
<form-bean name="loginForm" type="login.LoginForm" />
<form-bean ...
</form-beans>
...
</struts-config>
www.taringamberini.com MVC Struts 1 40
41. La classe ActionForm
Gli ActionForm sono associate alle Action attraverso il nome simbolico del form:
<struts-config>
<form-beans>
<form-bean name="loginForm" type="login.LoginForm" />
</form-beans>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 41
42. La classe ActionForm
Gli ActionForm possono essere messi in request od in session (default):
<struts-config>
<form-beans>
<form-bean name="loginForm" type="login.LoginForm" />
</form-beans>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 42
43. La classe ActionForm
Se fallisce la validazione dell'ActionForm si esegue forward all'input :
<struts-config>
<form-beans>
<form-bean name="loginForm" type="login.LoginForm" />
</form-beans>
<action-mappings>
<action
path="/login" type="login.LoginAction"
name="loginForm" scope="request" input="/login.jsp">
<forward name="success" path="/logged.jsp" />
<forward name="failure" path="/failure.jsp" />
</action>
</action-mappings>
</struts-config>
www.taringamberini.com MVC Struts 1 43
44. Ciclo di vita di una ActionForm
1. Il controller riceve una richiesta HTTP
2. Crea o riusa ActionForm
3. Inizializza proprietà dell' ActionForm: reset()
4. Salva ActionForm nello scope dichiarato
5. Popola ActionForm prendendo i dati dalla richiesta
HTTP
6. Valida proprietà dell'ActionForm: validate()
se errore si esegue forward all'input
2. altrimenti invoca il metodo execute() dell'Action
3. Forward alla view successiva con ActionForm nello scope
dichiarato
www.taringamberini.com MVC Struts 1 44
45. Inviare messaggi alla View
ActionForm e Action permettono di salvare
nella richiesta HTTP eventuali messaggi prima
dell'inoltro alla View successiva
ActionMessages rappresentano messaggi
informativi
ActionErrors (è un ActionMessages)
rappresentano messaggi d'errore
ActionMessages ed ActionErrors sono formati
da insiemi di più ActionMessage
www.taringamberini.com MVC Struts 1 45
46. Messaggi da un ActionForm
La validazione delle proprietà di un ActionForm salva automaticamente nella
richiesta Http gli ActionErrors impiegati per rappresentare insiemi di messaggi di
errori di validazione
public class LoginForm extends ActionForm {
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors actionErrors = new ActionErrors();
// se password troppo corta prepara un messaggio d'errore
ActionMessage actionMessage = new ActionMessage(
"login.form.validating.error.password.minLenght",
getPasswordMinLenght());
actionErrors.add("password", actionMessage);
return actionErrors;
}
}
www.taringamberini.com MVC Struts 1 46
47. Messaggi da un Action
Un Action può salvare nella richiesta HTTP sia ActionErrors, con
saveErrors(), che ActionMessages con saveMessages()
public class LoginAction extends Action {
public ActionForward execute(...) {
...
ActionMessage actionMessage = new ActionMessage("login.success", user);
ActionMessages actionMessages = new ActionMessages();
actionMessages.add(ActionMessages.GLOBAL_MESSAGE, actionMessage);
saveMessages(request.getSession(), actionMessages);
return mapping.findForward("success");
}
}
www.taringamberini.com MVC Struts 1 47
48. Struts Custom Tag Library - HTML
Utilizzata per interagire con tag HTML: input form,
checkbox, image, link, submit, text, textarea, ecc...
Dichiarazione nel web.xml (optional dalla 2.4):
<taglib>
<taglib-uri> http://struts.apache.org/tags-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
Dichiarazione in una JSP:
<%@ taglib uri="http://struts.apache.org/tags-html"
prefix="html" %>
www.taringamberini.com MVC Struts 1 48
49. Struts Custom Tag Library - HTML
Esempio di una JSP da cui effettuare il login:
<html:form action="/login.do">
<p><bean:message key="login.form.userName" />
<html:text property="userName" /></p>
<p><bean:message key="login.form.password" />
<html:password property="password" /></p>
<p><html:checkbox property="forgotPassword" />
<bean:message key="login.form.forgotPassword" /></p>
<html:submit />
</html:form>
www.taringamberini.com MVC Struts 1 49
50. Struts Custom Tag Library - Bean
Utilizzata per interagire con JavaBeans e resource
bundle: write, message, ecc...
Dichiarazione nel web.xml (optional dalla 2.4):
<taglib>
<taglib-uri>http://struts.apache.org/tags-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
Dichiarazione in una JSP:
<%@ taglib uri="http://struts.apache.org/tags-bean"
prefix="bean" %>
www.taringamberini.com MVC Struts 1 50
51. Struts Custom Tag Library - Bean
Esempio di una JSP dopo il login:
<p><bean:write name=” loginForm”
property=”userName” />
<bean:message key="logged.success" /></p>
Ove possibile preferire a <bean:write> il
<c:out> della JSTL:
<p><c:out value="loginForm.userName"/>
<bean:message key="logged.success" /></p>
www.taringamberini.com MVC Struts 1 51
52. Struts Custom Tag Library - Logic
Utilizzata per inserimento di HTML dinamico in modo
condizionale o iterativo: equal, notEqual, greaterThan,
lessEqual, iterate, ecc...
Dichiarazione nel web.xml (optional dalla 2.4):
<taglib>
<taglib-uri>http://struts.apache.org/tags-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
Dichiarazione in una JSP:
<%@ taglib uri="http://struts.apache.org/tags-logic"
prefix="logic" %>
www.taringamberini.com MVC Struts 1 52
53. Struts Custom Tag Library - Logic
Inserimento condizionale:
<logic:equal name="profiloUtenteForm" property="lettura"
value="true">
<p><bean:message key="login.form.userName" />
<html:text property="userName" disabled="true" /></p>
</logic:equal>
Ove possibile preferire a <logic:equal> il <c:if> della
JSTL:
<c:if test="${profiloUtenteForm.lettura eq 'true'}">
<p><bean:message key="login.form.userName" />
<html:text property="userName" disabled="true" /></p>
</c:if>
www.taringamberini.com MVC Struts 1 53
54. Struts Custom Tag Library - Logic
Inserimento iterativo:
<logic:iterate id="utente" name="listaUtentiForm" property="listaUtenti"
indexId="index">
<tr>
<td><bean:write name="index" /></td>
<td><bean:write name="utente" property="userName" /></td></tr>
</logic:iterate>
Ove possibile preferire a <logic:equal> il <c:if> della JSTL:
<c:forEach var="utente" items="${listaUtentiForm.listaUtenti}"
varStatus="loopTagStatus">
<tr>
<td>${loopTagStatus.index + 1 }</td>
<td>${utente.userName}</td></tr>
</c:forEach>
www.taringamberini.com MVC Struts 1 54
55. I18N
Resource bundle conformi alle convenzioni
della classe java.util.PropertyResourceBundle:
File di testo con estensione .properties
Ogni riga contiene una coppia key=value
Es. di un MessageResources_it.properties:
login.form.userName=Utente
login.form.password=Password
login.success=L'utente {0} si è loggato con successo.
Ultimo accesso il {1} alle ore {2}.
www.taringamberini.com MVC Struts 1 55
56. Bibliografia
JavaServer Pages Model 2 architecture:
http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-
jspmvc.html
Java BluePrints Enterprise Patterns:
http://java.sun.com/blueprints/patterns/MVC.html
The Java EE 5 Tutorial:
http://java.sun.com/javaee/5/docs/tutorial/doc/p1.html
Struts 1 User Guide:
http://struts.apache.org/1.3.9/userGuide/index.html
Programmare con Jakarta Struts – Chuck Cavaness – Ulrico
Hoepli Editore – 2003
Jakarta-Struts Live – Richard Hightower – SourceBeat, LLC,
Higland Ranch, Colorado - 2004
www.taringamberini.com MVC Struts 1 56