Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Applicazioni Web e pattern MVC con Java

Applicare il paradigma Model Control View allo sviluppo di applicazioni Web con Java/JSP.
Applicare il paradigma Model Control View allo sviluppo di applicazioni Web con Java/JSP.
Link copiato negli appunti

Spesso, quando si implementa un'applicazione Web utilizzando la tecnologia Java, si tende ad usare in modo indiscriminato Servlet e pagine JSP, assegnando ora ad una ora alle altre i più svariati compiti.

Se questa varietà di scelta da un lato consente ampia libertà al programmatore (e/o al progettista) dall'altro comporta, non di rado, degli errori di analisi e disegno dell'applicazione spesso determinanti. Se questa considerazione si rivela poco significativa (e poco intuitiva per il lettore) quando si tratta di semplici applicazioni facilmente riprogrammabili, riveste un ruolo fondamentale quando ci si imbatte in applicazioni più complesse come quelle di tipo enterprise.

Cos'è un Pattern

Anzitutto definiamo il concetto di pattern. Un pattern (letteralmente: modello) rappresenta un approccio standard utilizzato per risolvere problemi comuni. Nelle applicazioni web, solitamente, si fa ricorso a due principali tipi di pattern:

  • Architettura di tipo Model 1
  • Architettura di tipo Model 2, detta anche pattern Model-View-Controller (MVC)

L'architettura di tipo Model 1

Questo tipo di approccio viene utilizzato, per lo più, per applicazioni web che non richiedano particolari esigenze di processamento dati o che non implichino un particolare traffico di utenti.

Figura 1. Schema della logica alla base del Model 1
Schema della logica alla base del Model 1

In questo tipo di architettura la pagina JSP è responsabile sia della gestione della richiesta proveniente dal browser (request) sia della risposta da inviare successivamente al client (response).

A tal fine, alla pagina JSP è delegato il compito di interagire con le classi che costituiscono la parte business dell'applicazione, che sono implementate come JavaBeans. Tali classi rappresentano i dati relativi ai cosiddetti oggetti di business (business objects) per i quali forniscono dei metodi opportuni richiamabili dall'esterno.

La parte di salvataggio dei dati di business viene, infine, effettuata, solitamente, mediante l'utilizzo di un data base (o di un file, per applicazioni piuttosto elementari) che, nel grafico precedente, viene indicato come "Data store". In una applicazione ben strutturata, sarà buona norma scrivere delle classi ad hoc per la persistenza dei dati, delegando interamente ad esse le operazioni di I/O.

Esempio di architettura di tipo Model 1

L'applicazione che vogliamo costruire (impostata sulla falsariga di quella descritta nell'articolo sulla gestione degli errori nelle pagine JSP) deve consentire di inserire dei dati ad un utente attraverso una pagina HTML, salvare tali dati su un file di testo e visualizzare una pagina JSP che confermi l'inserimento effettuato ed i dati memorizzati.

Listato 1. Pagina HTML per l'inserimento dei dati

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>

<head>
<title>Inserimento Utente</title>
</head>

<body>
<h1>Inserimento utente</h1>
<p>Per inserire un utente riempire i campi sottostanti.<br />
Al termine,cliccare sul pulsante Invia.</p>

<form action="showUser.jsp" method="get">
<table cellspacing="5" border="0">
<tr>
<td align="right">Nome:</td>
<td><input type="text" name="nome" /></td>
</tr>
<tr>
<td align="right">Cognome:</td>
<td><input type="text" name="cognome" /></td>
</tr>
<tr>
<td align="right">Eta':</td>
<td><input type="text" name="eta" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Invia" /></td>
</tr>
</table>
</form>
</body>
</html>

Scriviamo una pagina JSP che legga i parametri in input provenienti dalla precedente form HTML, li salvi su un file avvalendosi delle due classi User (un semplice JavaBean) e UserIO e consenta di visualizzare, infine, i dati stessi.

Listato 2. Pagina JSP che prende i dati dal JavaBean

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Informazioni Utente salvate su file</title>
</head>
<body>
<%@ page import="business.User, dati.UserIO" %>

<%
String nome = request.getParameter("nome");
String cognome = request.getParameter("cognome");
String eta = request.getParameter("eta");

User user = new User(nome, cognome, eta);
UserIO.addItem(user, "./webapps/SimpleJSP/WEB-INF/etc/users.txt");
%>

<h1>Dati utente</h1>

<p>Ecco le informazioni relative all'utente inserito:</p>

<table cellspacing="5" cellpadding="5" border="1">
<tr>
<td align="right">Nome:</td>
<td><%= nome %></td>
</tr>
<tr>
<td align="right">Cognome:</td>
<td><%= cognome %></td>
</tr>
<tr>
<td align="right">Eta':</td>
<td><%= eta %></td>
</tr>
</table>

<p>Per inserire un nuovo utente, cliccare sul pulsante "Back"<br />
del browser oppure sul pulsante Nuovo Inserimento in basso.</p>

<form action="addUser.html" method="post">
<input type="submit" value="Nuovo Inserimento" />
</form>

</body>
</html>

Quello che segue è il codice della classe User, che implementa l'oggetto di business corrispondente all'utente inserito. La classe, è un JavaBean con le tre proprietà: nome, cognome ed eta.

Listato 3. JavaBean che fornisce i dati alla JSP

package business;

public class User
{
private String nome;
private String cognome;
private String eta;

public User(){}

public User(String nome, String cognome, String eta)
{
this.nome = nome;
this.cognome = cognome;
this.eta = eta;
}

public void setNome(String nome) {  this.nome = nome;  }
public String getNome() { return nome; }

public void setCognome(String cognome) { this.cognome = cognome; }
public String getCognome() { return cognome; }

public void setEta(String eta) { this.eta = eta; }
public String getEta() { return eta; }
}

La classe UserIO svolge il lavoro di scrittura su file. Implementa un solo metodo statico e scrive su un file (il cui path viene passato in input) il contenuto di un oggetto di tipo file.

Listato 4. Classe UserIO per la memorizzazione dei dati

package dati;

import java.io.*;
import business.*;

public class UserIO
{
public synchronized static void addItem(User user, String file)
throws IOException
{
PrintWriter out = new PrintWriter(new FileWriter(file, true));
out.println(user.getNome() + "-" + user.getCognome() + "-" +
user.getEta());
out.close();
}
}

Come è facile osservare, la pagina JSP interagisce direttamente sia con la classe di "business" User sia con la classe UserIO, che svolge le funzioni di scrittura su disco. Questo è, quindi, un chiaro esempio di utilizzo dell'architettura Model 1.

Il Pattern MVC (Architettura di tipo Model 2)

Come si è detto, il Model 1 rappresenta un approccio valido per applicazioni in cui il processamento dei dati è relativamente limitato. Nel caso inverso, invece, uno dei pattern più utilizzati per le applicazioni Web è il Model-View-Controller (MVC). Come si intuisce facilmente dal nome, tale pattern è costituito da 3 strati (o livelli o layers): il Model, la View ed il Controller.

Il Model

Rappresenta lo strato di business dell'applicazione ed è, solitamente, implementato attraverso l'uso dei JavaBeans.

La View

Rappresenta l'interfaccia utente, ovvero la web form (o le web form, visto che possono esserci molteplici viste per un dato memorizzato) con cui l'utilizzatore dell'applicazione si trova ad interagire. Spesso la view viene definita anche strato di presentazione (presentation layer). Poiché, la creazione delle interfacce utente ricavata attraverso le servlet è particolarmente onerosa e prona ad errori, la gestione della View viene totalmente delegata alle pagine HTML e/o JSP.

Il Controller

Si occupa di gestire il flusso dell'applicazione, sincronizzando il contenuto della View con quello del Model. Il componente web più indicato a svolgere tale tipo di funzione è sicuramente la servlet, la quale interagendo direttamente con il Model è facilmente in grado di aggiornare una o più View corrispondenti.

Figura 2. Schema del pattern MVC
Schema del pattern MVC

Quando si utilizza questo tipo di approccio è molto importante cercare di tenere i tre strati quanto più separati ed indipendenti possibile. Agendo in tal modo, infatti, si renderà di gran lunga più facile ed agevole la manutenzione del codice.

Se, per esempio, si decidesse di apportare delle modifiche ad un'applicazione in modo da visualizzare i dati in modo differente da quello già implementato, sarà sufficiente modificare soltanto il presentation layer senza minimamente intaccare gli altri due componenti del pattern MVC. Ancora meglio, sarà consigliabile, quando possibile, aggiungere ulteriori viste a quelle già implementate sfruttando, a tal proposito, al meglio i concetti della programmazione orientata agli oggetti.

Vediamo adesso come trasformare la precedente applicazione con l'utilizzo del pattern MVC.

La differenza sostanziale, in questo caso, è rappresentata dalla presenza di una servlet che svolga i compiti di controller precedentemente assegnati alla pagina JSP.

Listato 5. La servlet (strato di Controllo)

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.RequestDispatcher;
import business.User;
import dati.UserIO;

public class UserServlet extends javax.servlet.http.HttpServlet
{
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
String nome = request.getParameter("nome");
String cognome = request.getParameter("cognome");
String eta = request.getParameter("eta");

User user = new User(nome, cognome, email);
UserIO.addItem( user, "./webapps/SimpleJSP/WEB-INF/etc/users.txt");


RequestDispatcher dispatcher;
dispatcher = getServletContext().getRequestDispatcher("/../SimpleJSP/showUser.jsp");
dispatcher.forward(request,response);

}

public void doPost (HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request,response);
}
}

Le linee di codice evidenziate in rosso si occuperano di inoltrare le informazioni contenute nella request e nelle response alla pagina JSP la quale si occuperà soltanto di visualizzare i dati, ovvero curerà esclusivamente la parte di presentazione.

Listato 6. Pagina JSP (Strato di presentazione)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Informazioni Utente salvate su file</title>
</head>
<body>

<%
String nome = request.getParameter("nome");
String cognome = request.getParameter("cognome");
String eta = request.getParameter("eta");
%>

<h1>Dati utente</h1>

<p>Ecco le informazioni relative all'utente inserito:</p>

<table cellspacing="5" cellpadding="5" border="1">
<tr>
<td align="right">Nome:</td><td><%= nome %></td>
</tr>
<tr>
<td align="right">Cognome:</td><td><%= cognome %></td>
</tr>
<tr>
<td align="right">Eta':</td><td><%= eta %></td>
</tr>
</table>

<p>Per inserire un nuovo utente, cliccare sul pulsante "Back"<br />
del browser oppure sul pulsante Nuovo Inserimento in basso.</p>

<form action="addUser.html" method="post">
<input type="submit" value="Nuovo Inserimento">
</form>

</body>
</html>

E la pagina HTML iniziale, che contiene il primo form, dovrà modificare la action per puntare alla servlet invece che alla pagina JSP.

...
<form action="UserServlet" method="get">
...

Conclusioni

Probabilmente, con una semplice applicazione come quella del nostro esempio non si riescono a cogliere pienamente i vantaggi derivanti dall'utilizzo del pattern MVC ma è possibile già intuire come la suddivisione in tre strati possa facilitare la scalabilità e la manutenzione dell'applicazione.

Infine, è bene sottolineare l'importanza che rivestono le fasi di analisi e disegno relativamente a tutte le classi che compongono un'applicazione: maggiore sarà la cura dedicata a tali fasi e minore sarà l'impatto derivante dall'esigenza di apportare in seguito eventuali modifiche al codice.

Alla prossima.

Ti consigliamo anche