Utilizzo del Pattern MVC
Cosa si intende per
pattern?
Nell'ingegneria del software un pattern può essere definito "
una soluzione progettuale
generale ad un problema ricorrente", non è una libreria o un componente di software riusabile,
ma una descrizione o un modello da applicare per risolvere un problema che può
presentarsi in diverse situazioni durante la progettazione e lo sviluppo del software.
La differenza tra un algoritmo e un pattern è che il primo risolve problemi computazionali,
mentre il secondo è legato agli aspetti progettuali del software.
ARCHITETTURA J2EE IN BREVE
I 4 livelli dell'architettura J2EE:
- livello per la funzionalità del client(front end che risiedono sul client ) contiene le applicazioni che devono essere presentate all'utente finale.
- livello per il supporto web contiene tutte le componenti che estendono il tradizionale server Web,quindi servlet e JSP che sono eseguite sul server,a questo arrivano le richieste fatte dal client via HTTP e questo risponde generando codici HTML che vengono letti dal client.
- livello per la logica di business(EJB) contiene le componenti che gestiscono la logica applicativa, queste componenti elaborano dati seguendo le regole business dell'organizzazione.
- livello per l'integrazione EIS contiene le componenti per la gestioni dei dati della base di dati di back-end che sono eseguite sul server del data base.
I componenti essenziali di una applicazione J2EE sono le Jsp (Java server pages), le Servlet e gli Ejb (Enterprise java beans).
PATTERN MVC
Per introdurre il concetto del pattern MVC partiamo da un esempio: supponiamo di
avere due classi che devono scambiarsi dei valori, ovvero una classe deve prendere un
valore da un'altra classe e settarlo al suo interno,
un modo per risolvere questo problema e quello di crearsi due classi
dove all'interno dell'una viene instanziata e utilizzata l'altra. Di seguito l'esempio
di codice:
public class Model {
private int val;
public void setVal(
int val){
this.val = val;
}
public int getVal(){
return(val);
}
}
public class View {
//istanzio la classe Model
private Model model =
new Model();
private int val;
public void setVal(
int val){
this.val = val;
}
public int getVal(){
return(val);
}
public void scambiaVal(){
//Utilizzo la classe Model su istanziata
val = model.getVal();
}
}
Nel nostro caso all'interno della classe
View instanziamo la classe
Model e prendiamo il valore che ci serve. Tutto quello fin qui scritto
è corretto, risolve il problema ma non risponde a pieno alla filosofia della programmazione
ad oggetti perché nel momento in cui si dovesse usare la classe
View
mi dovrei sempre portare dietro la classe
Model in quanto le due sono
una dipendente dall'altra.
Per superare questo problema possiamo modificare le due classi ed aggiungerne una terza
in modo da non avere la dipendenza tra le classi
Model e
View.
L'esempio viene così modificato:
public class Model {
private int val;
public void setVal(
int val){
this.val = val;
}
public int getVal(){
return(val);
}
}
public class View {
private int val;
public void setVal(
int val){
this.val = val;
}
public int getVal(){
return(val);
}
}
public class Controller {
private Model model =
new Model();
private View view =
new View();
public void scambiaVal(){
this.val = val;
view.setVal(model.getVal());
}
}
In questo modo abbiamo tre classi di queste due sono indipendenti e abbiamo scritto una
terza classe che contiene la logica applicativa del progetto, che non sarà usata in
altri progetti.
Quindi nel caso i cui mi dovesse servire la classe
View definita in questo
progetto io posso usarla senza dovermi portare dietro la classe
Model
come succedeva nel caso precedente.
Per chi ha dimestichezza con l'UML quello descritto finora può essere rappresentato con i seguenti schemi:
Primo caso
Secondo caso
Vediamo come quel che è stato detto finora può essere applicato ad una web application:
Considerando lo schema illustrato sopra vediamo come opera una web application:
- il browser invia una richiesta al server web
- nel server web una Servlet ha il compito di gestire la richiesta con i dati inviati dal browser
- la Servlet istanzia un JavaBean e valorizza le proprietà delle classi con i valori recuperati dalla richiesta HTTP
- la Servlet chiama i metodi del JavaBean in modo da elaborare i dati
- la Servlet fa un Forward della richiesta alla Jsp che si deve preoccupare di visualizzare i dati a video
In una web Application quello che viene detto Controller, nell'esempio precedente,
sono le Servlet quello che è chiamato View sono le JSP e quello che è chiamato
Model sono i JavaBean, le Servlet dicono alle View come rappresentare i dati e al Model come gestirli.
L'architettura mostrata sopra, è un'implementazione server-side dello schema
Model/View/Controller.
Qui la componente presentazione ha il solo scopo di generare la risposta in HTML/XML da inviare al browser.
I componenti Front elaborano le richieste HTTP e sono responsabili della creazione dei
beans che saranno usati nella presentazione, nonché di scegliere a quale
componente della stessa rinviare la richiesta. I componenti Front possono
essere sia servlet che pagine JSP.
Il vantaggio di quest'architettura è che non avviene nessuna elaborazione nei componenti
della presentazione, il loro unico scopo è di inserire il contenuto dinamico
all'interno della parte statica.
Questo tipo di architettura separa chi deve scrivere codice Java da chi deve solo
preoccuparsi di scrivere codice HTML.
Il Model solitamente è il livello che si connette ai DataBase, ad EJB etc...
Se in produzione ci dicono di dover cambiare la pagina HTML in ingresso,
basta prendere un editor e modificare o l'HTML o la JSP, alla chiamata successiva
di quella funzione la JSP in automatico viene ricompilata e l'utente vedrà la nuova
versione, i vantaggi sono che non abbiamo fermato il servizio e che non abbiamo
dovuto toccare il codice della logica applicativa.
ESEMPIO
Questo semplice esempio di applicazione Web prende dei valori che vengono inseriti
dall'utente in una form HTML passandoli alla servlet che esegue la moltiplicazione
e li invia su una pagina JSP l'output della quale viene inviato al browser.
L'utente vedrà una pagina HTML con il risultato della moltiplicazione.
Codice Servlet
package mvc;
import mvc.JavaBean;
public class Servlet
extends javax.servlet.http.HttpServlet{
public void doPost(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException,
java.io.IOException{
javax.servlet.ServletContext sc;
javax.servlet.RequestDispatcher rd;
try{
mvc.JavaBean javaBean = null;
// istanzia il JavaBean
javaBean = new mvc.JavaBean();
request.setAttribute("javaBean", javaBean);
// inizializza la proprietà x del bean
javaBean.setX(Integer.parseInt(request.getParameter("x")));
// inizializza la proprietà y del bean
javaBean.setY(Integer.parseInt(request.getParameter("y")));
// Invoca moltiplica sul javaBean.
javaBean.moltiplica();
sc = getServletContext();
rd = sc.getRequestDispatcher("/ServletResults.jsp");
//si forwarda la risposta
rd.forward(request, response);
}
catch(
Throwable theException){
// Gestione errore
}
}
}
Codice JavaBean
package mvc;
public class JavaBean{
private int x = 0;
private int y = 0;
private int risultato = 0;
public JavaBean(){
super();
}
public void setRisultato(
int newRisultato){
risultato = newRisultato;
}
public int getRisultato(){
return(risultato);
}
public void setX(
int newX){
x = newX;
}
public int getX(){
return(x);
}
public void setY(
int newY){
y = newY;
}
public int getY(){
return(y);
}
public void moltiplica(){
risultato = x * y;
}
}
Codice Jsp
<HTML>
<HEAD></HEAD>
<BODY>
<jsp:useBean id="javaBean" class="mvc.JavaBean" scope="request"></jsp:useBean>
<TABLE border="0">
<TR>
<TD>risultato</TD>
<TD>
<%=javaBean.getRisultato() %>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>