10. Applicazione Web MVC [person] – Versione 5
10.1. Introduzione
In questa versione, stiamo apportando due modifiche:
La prima riguarda il modo in cui il client indica al server l'azione che desidera eseguire. Finora, questa veniva specificata utilizzando un parametro chiamato [action] nella richiesta GET o POST del client. Qui, l'azione sarà specificata dall'ultimo elemento dell'URL richiesto dal client, come mostrato nella seguente sequenza:

In [1], l'URL a cui è stato inviato il modulo è [/person5/do/validateForm]. È l'ultimo elemento [validateForm] dell'URL che ha permesso al controller di riconoscere l'azione da eseguire. In [2], il POST attivato dal link [Torna al modulo] è stato inviato all'URL [/person5/do/returnForm]. Anche in questo caso, l'ultimo elemento [returnForm] dell'URL indica al controller quale azione eseguire.
Stiamo introducendo questa modifica perché è il metodo utilizzato dai framework di sviluppo web più diffusi, come Struts o Spring MVC.
Tutti gli URL dell'applicazione avranno la forma [/person5/do/action]. Il file [web.xml] per l'applicazione [/person5] specificherà che accetta URL della forma [/do/*]:
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
Il controller recupererà il nome dell'azione da eseguire come segue:
Il metodo [getPathInfo] dell'oggetto [request] restituisce l'ultimo elemento dell'URL della richiesta.
La seconda modifica riguarda il modo in cui gli input dell'utente vengono memorizzati tra i cicli di richiesta/risposta. Attualmente, queste informazioni vengono memorizzate in una sessione. Questo approccio può presentare degli svantaggi se gli utenti sono molti e la quantità di dati da memorizzare per ciascuno di essi è elevata. Infatti, ogni utente ha la propria sessione personale. Inoltre, la sessione rimane attiva per un certo tempo dopo che un utente ha effettuato il logout, a meno che non sia stata fornita un'opzione di logout. Pertanto, 1.000 sessioni da 100 byte ciascuna occuperanno 1 MB di memoria. Questo rimane un requisito moderato e poche applicazioni hanno 1.000 sessioni attive contemporaneamente.
Tuttavia, esistono alternative alle sessioni che richiedono meno memoria ed è bene conoscerle. In questo caso, useremo il metodo dei cookie. Illustriamolo con un esempio.
Passaggio 1: l'utente invia un modulo:
![]() |
Questo ciclo di richiesta/risposta genera i seguenti scambi HTTP tra il client e il server:
[1]: [richiesta del client]
Questa è una richiesta POST standard. Non c'è nulla di insolito da notare qui, tranne che, anche se non useremo una sessione, il server web ne crea comunque una. Ciò è evidente dal token di sessione che il browser invia al server alla riga 11, che aveva precedentemente ricevuto dal server.
[2]: [risposta del server]
Possiamo notare che nelle righe 3 e 4 sono state inviate al browser del client delle intestazioni HTTP [Set-Cookie], una per il nome (riga 3) e una per l'età (riga 4). I valori di questi cookie sono quelli inviati nella riga 14 del POST [1] sopra riportato.
Fase 2: Ritorno al modulo

Questo ciclo di richiesta/risposta genera i seguenti scambi HTTP tra il client e il server:
[1]: [richiesta del client]
Qui vediamo la richiesta POST generata cliccando sul link [Torna al modulo]. Alla riga 11, vediamo che il browser rimanda al server i cookie ricevuti [name, age, JSESSIONID] utilizzando l’intestazione HTTP [Cookie]. È così che funzionano i cookie. Il client rimanda al server i cookie che il server gli ha inviato. In questo esempio, il controller riceverà i valori [pauline, 18], che dovrà inserire nei campi [txtName, txtAge] della vista [form] visualizzata in [2].
[2]: [risposta del server]
Non c'è nulla di particolare da notare qui, se non il fatto che in questa risposta il server non ha inviato alcun cookie. Ciò non impedirà al browser di rispedire tutti i cookie ricevuti dal server nello scambio successivo, anche se ciò non serve a nulla. Riduciamo quindi il carico sulla memoria disponibile del server a costo di un aumento del flusso di caratteri negli scambi client/server.
10.2. Il progetto Eclipse
Per creare il progetto Eclipse [mvc-personne-05] per l'applicazione web [/personne5], duplicare il progetto [mvc-personne-04] seguendo la procedura descritta nella sezione 6.2.
![]() | ![]() |
10.3. Configurazione dell'applicazione web [personne5]
Il file web.xml per l'applicazione /personne5 è il seguente:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>mvc-personne-05</display-name>
<!-- ServletPersonne -->
<servlet>
<servlet-name>personne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletPersonne
</servlet-class>
...
</servlet>
<!-- Mapping ServletPersonne-->
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/do/*</url-pattern>
</servlet-mapping>
<!-- welcome files -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Questo file è identico a quello della versione precedente, tranne che per alcuni dettagli:
- riga 6: il nome visualizzato dell'applicazione web è cambiato in [mvc-personne-05]
- riga 18: gli URL gestiti dall'applicazione hanno il formato [/do/*]. In precedenza, veniva gestito solo l'URL [/main]. Ora, gli URL sono tanti quanti sono le azioni da gestire.
La pagina iniziale [index.jsp] cambia:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/do/formulaire"/>
- riga 5: la pagina [index.jsp] reindirizza il client all'URL [/person5/do/form], il che equivale a chiedere al controller di eseguire l'azione [form].
10.4. Il codice della vista
Le viste [form, response, errors] cambiano molto poco. L'unica modifica è che l'azione da eseguire non è più specificata come prima, quando era definita in un campo nascosto denominato [action] nei moduli inviati. Ora è definita nell'URL di destinazione dei moduli inviati, ovvero nell'attributo [action] del tag <form>:
[form.jsp]:
...
<html>
<head>
<title>Personne - formulaire</title>
<script language="javascript">
...
</script>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="validationFormulaire" method="post">
...
</form>
</center>
</body>
</html>
- Riga [13]: Il parametro [action] del modulo ricompare dopo essere stato assente per un certo periodo nelle versioni precedenti. Per comprendere il valore di questo attributo in questo contesto, ricordiamo che tutti gli URL elaborati dall'applicazione hanno la forma [/do/action]. Nella riga [13], l'attributo [action] ha come valore un URL relativo (che non inizia con /). Pertanto, il browser lo completerà con l'URL della pagina attualmente visualizzata, che è necessariamente un URL del tipo [/do/action]. L'ultimo elemento sarà sostituito dall'URL relativo dell'attributo [action] del tag <form> per ottenere l'URL [/do/validationFormulaire] come destinazione POST.
- Il campo nascosto [action] è scomparso
[response.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- riga [7]: la destinazione POST sarà [/do/returnForm]
- Il campo nascosto [action] è stato rimosso dal modulo nelle righe 7–8.
[errors.jsp]:
...
<html>
...
<body>
...
<form name="frmPersonne" action="retourFormulaire" method="post">
</form>
<a href="javascript:document.frmPersonne.submit();">
${lienRetourFormulaire}
</a>
</body>
</html>
- riga [6]: la destinazione POST sarà [/do/returnForm]
- Il campo nascosto [action] è stato rimosso dal modulo nelle righe 6–7.
I lettori sono invitati a testare queste nuove viste utilizzando l'approccio illustrato nelle versioni precedenti.
10.5. Il controller [ServletPersonne]
Il controller [ServletPersonne] dell'applicazione web [/personne5] gestirà le seguenti azioni:
No. | richiesta | origine | elaborazione |
1 | [GET /person5/do/form] | URL inserito dall'utente | - invia la vista [form] vuota |
2 | [POST /person5/do/formValidation] con i parametri [txtName, txtAge] pubblicato | fare clic sul pulsante [Invia] nel [modulo] | - controlla i valori dei parametri [txtName, txtAge] - se non sono corretti, inviare la vista [errors(errors)] - se sono corretti, invia la vista [response(name,age)] |
3 | [POST /person5/do/returnForm] senza parametri inviati | Clicca sul [Torna al modulo] dalla [risposta] e [errori]. | - inviare la vista [modulo] precompilata con gli ultimi valori inseriti |
Lo scheletro del controller [ServletPersonne] è identico a quello della versione precedente. Esamineremo le modifiche apportate ai metodi [doValidationFormulaire, doRetourFormulaire, doGet]; i metodi [init, doInit, doPost] rimangono invariati.
10.5.1. Il metodo [doGet]
Il metodo [doGet] non recupera l'azione da eseguire allo stesso modo delle versioni precedenti:
- riga 12: recupera l'azione da eseguire. Ha il formato [/action].
- righe 18–22: elaborazione dell'azione [/form] richiesta da una richiesta GET
- righe 23–27: elaborazione dell'azione [/validateForm] richiesta da una richiesta POST
- righe 28–32: elaborazione dell'azione [/returnForm] richiesta da una richiesta POST
10.5.2. Il metodo [doValidationFormulaire]
Questo metodo elabora la richiesta n. 2 [POST /person5/do/validationFormulaire] con [txtName, txtAge] negli elementi inviati. Il suo codice è il seguente:
Novità:
- Il metodo [doValidationFormulaire] restituisce una delle viste [response, errors]. Indipendentemente dalla risposta, il controller imposta due cookie al suo interno, righe 8–9. Un cookie è rappresentato da un oggetto [Cookie] il cui costruttore accetta due parametri: la chiave del cookie e il valore ad essa associato.
- riga 8: il valore inserito per il nome viene inserito in un cookie con la chiave "name"
- riga 9: il valore inserito per l'età viene inserito in un cookie con la chiave "age"
- Un cookie viene aggiunto alla risposta HTTP inviata al client utilizzando il metodo [response.addCookie]. Questa risposta viene solo preparata qui. Verrà effettivamente inviata solo quando verrà eseguita la pagina JSP della vista inviata al client.
10.5.3. Il metodo [doRetourFormulaire]
Questo metodo elabora la richiesta n. 2 [POST /person5/do/retourFormulaire] senza alcun dato inviato. Il suo codice è il seguente:
Novità:
Il metodo [doRetourFormulaire] dovrebbe visualizzare un modulo precompilato con i dati più recenti. Nella versione precedente, questi venivano memorizzati nella sessione. In questa versione, non utilizziamo più la sessione, ma ricorriamo ai cookie per memorizzare i dati tra uno scambio client-server e l'altro. Quando il client richiedeva la convalida del modulo, riceveva in risposta la vista [response] o [errors], a seconda dei casi, insieme a due cookie denominati "name" e "age". Quando si fa clic sul link [Torna al modulo] su queste due viste — il che innesca una richiesta POST all'URL [/do/retourFormulaire] — il browser invia i due cookie ricevuti al server.
- Righe 4–18: Recuperiamo i valori dei cookie denominati "name" e "age". Stranamente, non esiste un metodo per recuperare il valore di un cookie in base alla sua chiave. Pertanto, dobbiamo iterare attraverso ciascuno dei cookie ricevuti.
- Una volta fatto ciò, i due valori ottenuti vengono inseriti nel modello della vista [form] (righe 20–21) in modo che possa visualizzarli.
10.6. Test
Avviare o riavviare Tomcat dopo aver integrato il progetto Eclipse [person-mvc-05] al suo interno, quindi richiedere l'URL [http://localhost:8080/personne5].


