Un framework per il
pattern MVC
Simone Pulcini
Oggi parleremo di:





Framework
Design Pattern e MVC
Contoller in Struts e Servlet
Model in Struts e Form Bean
View in Struts e Java Server Pages (JSP)
Framework: definizione

Insieme di librerie di codice


Favorisce riusabilità del codice e permette di
concentrarsi sullo sviluppo di funzionalità proprie.



Implementano funzionalità per sviluppare una propria
applicazione software
Sviluppo come integrazione
Funzionalità del framework documentate attraverso le API.
Sovrainsieme delle librerie run-time proprie del
linguaggio.

Offre funzionalità specifiche
Design Pattern



Soluzione riutilizzabile ad un problema
comune nello sviluppo di software
Soluzione proposta non è implementazione
diretta.
Descritta attraverso un template, per astrarre
dal linguaggio di sviluppo e dal caso specifico
Design Pattern MVC





Separa logica operativa da interfaccia utente.
Interfaccia utente detta VIEW
Sorgenti di dati identificate dal MODEL
Interazione gestita dal CONTROLLER; notifica il
MODEL di richieste di cambiamenti risultanti
dalle interazioni.
MODEL notifica VIEW dei cambiamenti nei dati
MVC: Diagramma
Controller
View
Model
Problemi MVC su Web

Connessioni senza stato fra client e server



Come notificare modifiche nel model?
Browser deve reinterrogare il server per scoprire
modifiche nello stato dell’applicazione
Differenze nella tecnologia di
implementazione fra client e server
MVC Model 2
Struts e MVC



Struts: framework che implementa il pattern
MVC per lo sviluppo di web applications
Struts integra ed estende alcuni componenti
di Java Enterprise Edition
Arricchisce le API Java per la gestione delle
Servlet e offre tag aggiuntivi per le Java
Server Pages (JSP)
Diagramma di una
applicazione Struts
Web Browser
Application Server
View
JSP
Model
ActionForm beans
Controller
Struts-config.xml e Actions
Ruoli

Client browser


Controller


Aggiorna lo stato del modello e aiuta a controllare il flusso dell’applicazione. Realizzato
mediante una Action class.
Model state


Riceve la richiesta e decide a chi mandarla. Riflette il pattern Command ed è
implementato come servlet. Configurato in struts-config.xm
Business logic


Produce eventi di richiesta e attende una risposta.
Rappresenta lo stato dell’applicazione. Rappresentato da bean ActionForm a livello di
sessione o richiesta, non a livello di persistenza. Informazione dalla ActionForm letta
mediante tag JSP.
View

Componente JSP senza logica di flusso o di business o informazione di modello, solo
tag.
Componenti chiave



"request" handler fornito dall’applicazione,
associato a uno URI standard.
"response" handler trasferisce il controllo a
un’altra risorsa che completa la risposta.
Biblioteca di tag per creare applicazioni
interattive, basate su form, con pagine lato
server.
Controller in Struts
Controller di Struts basato su 4 componenti:

1.
2.
3.
4.

ActionServlet
Action
Plugins
RequestProcessor
Flusso di web application: da richiesta dal
client a risposta offerta da application server
Servlet: definizione



Componente di web application Java EE
Programma Java che gira lato server
(differentemente da una applet che gira lato
client)
Classe java che estende funzionalità offerte
da un server (HTTP, FTP, SMTP ecc.)

HttpServlet (da javax.servlet.http)
Architettura
Separation of concerns per
Web applications




Per-action logic
Accesso agli oggetti necessari per eseguire
la logica dell’azione e accedere alle risorse
Traduzione, associazione e conversione da
valore stringa in HTML a tipi e primitive e da
oggetti vista a oggetti business
Cross-cutting concerns per fornire
funzionalità a gruppi di azioni o a tutte le
azioni nell’applicazione.
Ciclo di vita
Servlet: ciclo di vita





Richiesta da client ad application server
Application server verifica in web.xml a quale servlet
mappare la richiesta
Classe Servlet indicata nel descrittore viene caricata,
istanziata, e inizializzata dal Servlet Container
La classe genera la risposta alla richiesta ricevuta dal
client [doGet(); oppure doPost();]
Se non vi sono altre richieste da soddisfare con tale
servlet, Servlet Container chiama il metodo destroy()
ActionServlet: la servlet di
Struts





Controller si innesta estendendo ActionServlet
Questa servlet raccoglierà tutte le richieste conformi ad un certo
pattern, opportunamente dichiarato nel file web.xml
Ma se c’è una sola servlet che raccoglie tutte le richieste,
come differenzio le risposte?
ActionServlet prende come parametro un file di configurazione
(struts-config.xml) nel quale lo sviluppatore può dichiarare i
mapping fra una risorsa richiesta (path), la logica di risposta
(Action) e la pagina JSP che produce il risultato (View)
Struts genera opportunamente il codice di risposta dei metodi
doGet o doPost in base a quanto dichiarato nel file di
configurazione struts-config.xml
Esempio: WEB.XML


E’ il file di descrittore di ciascuna WEB
APPLICATION. Viene letto dall’application
Server. NON E’ UN FILE DI
CONFIGURAZIONE DI STRUTS
In esso però scriveremo una dichiarazione ad
hoc per far si che ogni richiesta venga
elaborata da una particolare servlet che
estende la ActionServlet delle API di Struts
WEB.XML
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servletclass>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
….
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
Struts-config.xml; tag <action>




Indica mapping fra risorse View, Controller, Model
Tag <action>
All’interno si dichiara in quale classe è implementata la
logica di controllo che deve gestire la richiesta di una
risorsa effettuata dal client, quale è la view e quale è il
model con il quale si devono rappresentare i dati
Esaminiamo, per concludere il discorso sul Controller,
i tipi di classi Action messi a disposizione da Struts e
vediamo eventualmente come definire una nostra
Action che implementa una logica non identificabile tra
le Action già implementate in Struts
Actions in Struts
Ogni classe di tipo Action deve estendere la classe
org.apache.struts.action.Action
 Ogni Action deve ridefinire il metodo execute() che ha la
seguente segnature:
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception
 Non è compito dello sviluppatore istanziare la classe
ACTION!!!
 Sarà la ActionServlet, in base a quanto dichiarato nel file di
configurazione struts-config.xml, ad istanziare la corretta Action e
a chiamare il metodo execute in essa ridefinito.

Esempio di Action
package org.prova;
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 TestAction extends Action {
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
// Logica di controllo (codice Java) …
…
//al termine devo restituire una istanza di ActionForward per soddisfare
//la segnatura del metodo execute()
return mapping.findForward("testAction");
}
}
Struts-config.xml: tag <action>
<action-mappings>
<action path="/TestAction"
type=“org.prova.TestAction">
<forward name="testAction"
path="/pages/TestAction.jsp"/>
</action>
</action-mappings>
Actions Built-in di Struts


Vi sono alcune Action già implementate che offrono
funzionalità comuni. Possibile usarle direttamente.
org.apache.struts.actions.DispatchAction


Riceve valore che può funzionare come discriminante in un
parametro della URL. Invece di execute, un metodo per ogni
valore di tale parametro. A seconda del valore presente nel
parametro, Struts chiamerà il metodo corrispondente
org.apache.struts.actions.ForwardAction

Chiama pagina jsp. Non richiede nessuna implementazione di
codice ma solo dichiarazione opportuna in tag <action>
Esempio di Dispatch Action
package org.prova;
import java.io.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.apache.struts.actions.DispatchAction;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class Dispatch_Action extends DispatchAction {
public ActionForward add(
ActionMapping mapping, ActionForm form, HttpServletRequest request
HttpServletResponse response) throws Exception {
System.out.println("You are in add function.");
return mapping.findForward("add");
}
Dispatch action (contd.)
public ActionForward edit(
ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
System.out.println("You are in edit function.");
return mapping.findForward("edit");
}
}
Dispatch Action:
struts-config.xml
<action
path="/DispatchAction"
type=“org.prova.Dispatch_Action"
parameter=“discrimina"
input="/pages/DispatchAction.jsp"
name="DispatchActionForm">
<forward name="add" path="/pages/DispatchActionAdd.jsp" />
<forward name="edit" path="/pages/DispatchActionEdit.jsp" />
<forward name="search“ path="/pages/DispatchActionSearch.jsp"/>
</action>
ForwardAction:
struts-config.xml
Forward Action richiede sola configurazione;
non è necessario scrivere codice Java
<action
path="/success"
type="org.apache.struts.actions.Forward
Action"
parameter="/pages/Success.jsp"
input="/pages/ForwardAction.jsp“>
</action>

Model in Struts



Struts non dettaglia scelte specifiche sulle
componenti che riguardano il Modello.
Fondamentalmente il Modello deve occuparsi
del reperimento di dati e informazioni
ignorando comunque come esse verranno
presentate nella View
Per il modello vi sono molte API che
permettono ad esempio l’interfacciamento
con un database (JDBC, Hibernate…)
ActionForm: il punto di
raccordo tra Model e View




Struts prevede struttura di supporto per raccordare i
dati ottenuti dal modello e renderli più facilmente
manipolabili da una View.
ActionForm: Java Bean estende
org.apache.struts.action.ActionForm, le cui variabili
membro contengono i valori di un form html dichiarato
nella view (oltre eventuali parametri passati nella URL
e tag di tipo “hidden”)
ActionForm popolato automaticamente da Struts
Ogni pagina jsp “dovrebbe” contenere la dichiarazione
di un form html. Attraverso opportuni tag dichiaritivi
contenuti nella pagina JSP, Struts sarà in grado di
popolare il bean associato a tale form
ActionForm: esempio
package org.prova;
import org.apache.struts.action.ActionForm;
public class DispatchActionForm extends ActionForm {
private String discriminante =" ";
public String getDiscriminante( ) {
return discriminante;
}
public void setDiscriminante(String discriminante) {
this.discriminante = discriminante
}
Action Form: struts-config.xml
<form-bean name="DispatchActionForm"
type=“org.prova.DispatchActionForm"/
>
View in Struts


Struts estende Java Server Pages (JSP)
aggiungendo ulteriori tag a quelli già presenti
Prima di vedere alcuni esempi però è
necessario richiamare alcuni concetti di base
riguardanti le pagine JSP
JSP: definizione e ciclo di vita




Java Server Pages è una tecnologia per la realizzazione di
pagine web con contenuti dinamici
Una pagina JSP può contenere:
1.
Tag HTML
2.
Tag XML definiti in apposite librerie esterne (Tag Libraries)
3.
Codice Java inserito in apposite sezioni denominate “Scriptlet”
Una pagina JSP viene caricata dall’application Server e
tradotta in nell’output finale, HTML, subendo però un processo
di generazione intermedio. Il container che si occupa di
tradurre le JSP genera infatti una Servlet (JSP Page
Implementation Class)
Il codice Java della Servlet si occupa di creare dinamicamente
sullo stream di Output il sorgente HTML che viene offerto quale
risposta alla richiesta effettuata dal client
JSP: Tag Libraries 1/2
Le specifiche JSP prevedono tag di base
identificabili dal prefisso “jsp”
 In generale un tag ha un prefisso relativo alla
tag library di appartenenza seguito dal nome
della funzionalità che si intende utilizzare:
<nome_prefisso:nome_funzione>…</nome_pr
efisso:nome_funzione>

JSP: Tag Libraries 2/2



Tag library è composta da un jar e da un file “.tld” che
descrive il contenuto del jar. Ha una sintassi specifica.
Il jar e il tld permettono all’opportuno componente
dell’application server di tradurre i tag in frammenti di
codice java. L’application server sa dell’esistenza di
nuove tag libraries perché file web.xml avrà ricevuto le
opportune modifiche per le nuove dichiarazioni di tag
libraries aggiuntive
Processo di traduzione da JSP in Servlet e produzione
del codice HTML di output interamente server-side
JSP: scriptlet



Codice Java incluso direttamente, racchiuso
tra opportuni marcatori; se necessario si
possono anche scrivere tag html.
Problema manutenzione di JSP contenente
scriptlet, HTML e tag appartenenti a librerie
Esistono oggi molte tag libraries, comprese
quelle aggiunte da Struts e le note JSTL, che
permettono tramite tag di rendere una pagina
JSP facilmente “scriptless” 
Tag Libraries di Struts



Bean: contiene tag per la manipolazione e
l’accesso di Java Bean
Html: contiene tag per creare form HTML
gestibili attraverso Struts e ulteriori tag per
generare altri elementi html (ovvero
permettono di non usare direttamente tag
HTML dentro la pagina JSP)
Logic: contiene tag per riprodurre logica
decisionale, cicli iterativi e valutazioni di valori
Esempio finale



Faremo vedere i componenti di una mini web
application struts che visualizza una pagina
con un form nel quale è possibile inserire un
numero
Se questo numero è uguale ad 1 verrà
visualizzato una pagina con un messaggio di
successo.
In ogni altro caso verrà visualizzata una
pagina di insuccesso.
Form bean

Ci serve un bean in cui memorizzare il numero che verrà inserito nel
form visualizzato dall’utente.
package org.prova;
import org.apache.struts.action.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogicForm extends ActionForm {
private long number;
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number=number;
}
}
Pensiamo ora alla Action

Non ha bisogno di logica operativa
particolare; dovrà soltanto restituire il
mapping alla pagina successiva (ovvero la
pagina dove esaminerò il valore introdotto
dall’utente e stamperò un msg di
successo/insuccesso)
Action
package org.prova;
import java.io.*;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import org.apache.struts.action.*;
public class LogicAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
//Il mapping identificato dalla stringa “success” si trova in struts-config.xml
return mapping.findForward("success");
}
}
Configuriamo lo struts-config.xml
per il bean e per la action
<form-bean
name="LogicForm" type=“org.prova.LogicForm" />
<action path="/LogicAction"
type=“org.prova.LogicAction"
name="LogicForm"
input="/pages/InputLogic.jsp">
<forward name="success"
path="/pages/output.jsp"/>
</action>
InputLogic.jsp
<%@ taglib uri="/tags/struts-html" prefix="html" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<html:html>
<head>
<title>Esempio tag Logic</title>
</head>
<body>
<html:form action="/LogicAction" method ="post">
<h2>Enter a number:</h2>
<html:text property="number"/>
<br>
InputLogic.jsp (contd.)
<br>
<h3>Nella pagina di output logic:equal funzionerà se il valore
inserito sarà 1</h3>
<h3>altrimenti verrà eseguito logic:notEqual</h3>
<br>
<html:submit value="Submit"/>
<html:cancel/>
</html:form>
</body>
</html:html>
Output.jsp
<%@ taglib uri="/tags/struts-bean" prefix="bean" %>
<%@ taglib uri="/tags/struts-logic" prefix="logic" %>
<html>
<head>
<title>Verifichiamo il dato...</title>
</head>
<body>
<h3>Il momento della verifica!!!!!</h3>
<h4>Il numero inserito è:</h4>
Output.jsp
<bean:write name="LogicForm" property="number"/></h4>
<logic:equal name="LogicForm" property="number" value="1">
<h4>Hai immesso il numero 1 e sono entrato nel tag equal</h4>
</logic:equal>
<logic:notEqual name="LogicForm" property="number"
value="1">
<h4>Hai immesso un numero diverso da 1 e sono entrato nel tag
notEqual</h4>
</logic:notEqual>
</body>
</html>
Fonti:




Chuck Cavaness, Programming Jakarta
Struts, 2nd Edition, O’Reilly, 2004
http://struts.apache.org/
http://www.infoq.com/minibooks/startingstruts2
http://www.roseindia.net/struts/