6. Aplicación web MVC [personne] – versión 2
Ahora vamos a proponer variantes de la aplicación [/personne1] anterior, a las que llamaremos [/personne2, /personne3, ...]. Estas variantes no modifican la arquitectura inicial de la aplicación, que sigue siendo la siguiente:

En el caso de estas variantes, nuestras explicaciones serán más breves. Solo presentaremos los cambios introducidos con respecto a la versión anterior.
6.1. Introducción
Ahora nos proponemos añadir a nuestra aplicación una gestión de sesiones. Recordemos los siguientes puntos:
- el diálogo cliente-servidor HTTP es una sucesión de secuencias de solicitud-respuesta inconexas entre sí
- la sesión sirve de memoria entre las diferentes secuencias de solicitud-respuesta de un mismo usuario. Si hay N usuarios, hay N sesiones.
La siguiente secuencia de pantallas muestra lo que ahora se espera del funcionamiento de la aplicación:
Intercambio n.º 1
![]() | ![]() |
La novedad radica en el enlace de vuelta al formulario que se ha añadido en la vista [erreurs].
Intercambio n.º 2
![]() | ![]() |
En el intercambio n.º 1, el usuario proporcionó los valores (xx, yy) para el par (nombre, edad). Si durante el intercambio el servidor tuvo conocimiento de estos valores, al final del intercambio los «olvida». Sin embargo, se puede observar que, durante el intercambio n.º 2, es capaz de volver a mostrar sus valores en su respuesta. Es el concepto de sesión el que, en este caso, permite al servidor web memorizar datos a lo largo de los sucesivos intercambios entre el cliente y el servidor. Existen otras soluciones posibles para resolver este problema.
Durante el intercambio n.º 1, el servidor memorizará en la sesión el par (nombre, edad) que el cliente le ha enviado para poder mostrarlo durante el intercambio n.º 2.
He aquí otro ejemplo de implementación de la sesión entre dos intercambios:
Intercambio n.º 1
![]() | ![]() |
La novedad es el enlace de vuelta al formulario que se ha añadido en la página de la respuesta.
Intercambio n.º 2
![]() | ![]() |
6.2. El proyecto Eclipse
Para crear el proyecto Eclipse [mvc-personne-02] de la aplicación web [/personne2], vamos a duplicar el proyecto Eclipse [mvc-personne-01] con el fin de recuperar lo ya existente. Para ello, procedamos de la siguiente manera:
[clic droit sur projet mvc-personne-01 -> Copy]:

y, a continuación, [clic droit dans Package Explorer -> Paste]:
![]() | ![]() - Indiquemos en [1] el nombre del nuevo proyecto y en [2] el nombre de una carpeta existente pero vacía |
Se crea entonces el proyecto [mvc-personne-02]:

Por el momento, es idéntico al proyecto [mvc-personne-01]. Tendremos que realizar algunas modificaciones manualmente antes de poder utilizarlo. Accedamos a la vista [Servers] e intentemos añadir esta nueva aplicación a las gestionadas por Tomcat:
![]() | ![]() |
Vemos que, en [1], Tomcat no detecta el nuevo proyecto [mvc-personne-02]. Para que lo detecte, hay que modificar un archivo de configuración del proyecto [mvc-personne-02]. Utilicemos la opción [File / Open File] para abrir el archivo [<mvc-personne-02>/.settings/.component]:
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId">
<wb-module deploy-name="mvc-personne-01">
<wb-resource deploy-path="/" source-path="/WebContent"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src"/>
<property name="java-output-path" value="/build/classes/"/>
<property name="context-root" value="personne1"/>
</wb-module>
</project-modules>
La línea 3 indica el nombre del módulo web que se va a implementar en Tomcat. Este nombre es, en este caso, el mismo que el del proyecto [mvc-personne-01]. Lo cambiamos por [mvc-personne-02]:
<wb-module deploy-name="mvc-personne-02">
Además, podemos aprovechar para modificar, en la línea 7, el nombre del contexto de la aplicación [mvc-personne-02], que entra en conflicto con el del proyecto [mvc-personne-01]:
<property name="context-root" value="personne2"/>
Esta segunda modificación se podía realizar directamente desde Eclipse. Sin embargo, no he visto cómo hacer la primera sin pasar por el archivo de configuración.
Una vez hecho esto, guardamos el nuevo archivo [.content], cerramos Eclipse y lo reiniciamos para que se apliquen los cambios.
Una vez reiniciado Eclipse, intentemos realizar la operación que falló anteriormente:
![]() | ![]() |
Esta vez, el proyecto [mvc-personne-02] se detecta correctamente. Lo añadimos a los proyectos configurados para ser ejecutados por Tomcat:

6.3. Configuración de la aplicación web [personne2]
El archivo web.xml de la aplicación /persona2 es el siguiente:
<?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-02</display-name>
<!-- ServletPersonne -->
<servlet>
<servlet-name>personne</servlet-name>
<servlet-class>
istia.st.servlets.personne.ServletPersonne
</servlet-class>
<init-param>
<param-name>urlReponse</param-name>
<param-value>
/WEB-INF/vues/reponse.jsp
</param-value>
</init-param>
<init-param>
<param-name>urlErreurs</param-name>
<param-value>
/WEB-INF/vues/erreurs.jsp
</param-value>
</init-param>
<init-param>
<param-name>urlFormulaire</param-name>
<param-value>
/WEB-INF/vues/formulaire.jsp
</param-value>
</init-param>
<init-param>
<param-name>urlControleur</param-name>
<param-value>
main
</param-value>
</init-param>
<init-param>
<param-name>lienRetourFormulaire</param-name>
<param-value>
Retour au formulaire
</param-value>
</init-param>
</servlet>
<!-- Asignación ServletPersonne-->
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<!-- archivos de bienvenida -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Este archivo es idéntico al de la versión anterior, salvo que declara dos nuevos parámetros de inicialización:
- línea 6: el nombre de visualización de la aplicación web ha cambiado a [mvc-personne-02]
- líneas 31-36: definen el parámetro de configuración denominado [urlControleur], que es la URL [main] que conduce al servlet [ServletPersonne]
- Líneas 37-42: definen un parámetro de configuración denominado [lienRetourFormulaire], que es el texto del enlace de retorno al formulario desde las páginas JSP, [erreurs.jsp] y [reponse.jsp].
La página de inicio [index.jsp] cambia:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
response.sendRedirect("/personne2/main");
%>
- línea 5: la página [index.jsp] redirige al cliente a la URL del controlador [ServletPersonne] de la aplicación [/personne2].
6.4. El código de las vistas
6.4.1. La vista [formulaire]
Esta vista es idéntica a la de la versión anterior:

Se genera a partir de la página JSP [formulaire.jsp] siguiente:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// se recuperan los datos de la plantilla
String nom=(String)session.getAttribute("nom");
String age=(String)session.getAttribute("age");
String urlAction=(String)request.getAttribute("urlAction");
%>
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form action="<%=urlAction%>" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="<%= nom %>" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="<%= age %>" type="text" size="3"></td>
</tr>
<tr>
</table>
<table>
<tr>
<td><input type="submit" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="button" value="Effacer"></td>
</tr>
</table>
<input type="hidden" name="action" value="validationFormulaire">
</form>
</center>
</body>
</html>
Novedades:
- En la línea 19, el formulario tiene ahora un atributo [action] cuyo valor es la URL a la que el navegador deberá enviar los valores del formulario cuando el usuario haga clic en el botón [Envoyer] de tipo submit. La variable [urlAction] tendrá el valor action="main". La vista [formulaire] se muestra tras las siguientes acciones del usuario:
- solicitud inicial: GET /persona2/principal
- clic en el enlace [Retour au formulaire]: GET /persona2/main?action=retourFormulaire
Dado que el atributo [action] no especifica una URL absoluta (que comience por /), sino una URL relativa (que no comience por /), el navegador utilizará la primera parte de la URL de la página que se muestra actualmente, [/personne2], y le añadirá la URL relativa. Por lo tanto, la URL de POST será [/personne2/main], la del controlador. Esta solicitud POST irá acompañada de los parámetros [txtNom, txtAge, action] de las líneas 23, 27 y 38.
- Línea 8: se recupera el valor del elemento [urlAction] del modelo. Se busca en los atributos de la solicitud actual. Se utilizará en la línea 19.
- Líneas 6-7: se recuperan los valores de los elementos [nom, age] del modelo. Se buscan en los atributos de la sesión y ya no en los de la consulta, como en la versión anterior. Esto se hace para satisfacer las necesidades de la consulta [GET /personne2/main?action=retourFormulaire] del enlace de las vistas [réponse] y [erreurs]. Antes de mostrar estas dos vistas, el controlador almacena en la sesión los datos introducidos en el formulario, lo que le permite recuperarlos cuando el usuario utiliza el enlace [Retour au formulaire] de las vistas [réponse] y [erreurs].
6.4.2. La vista [reponse]
Esta vista muestra los valores introducidos en el formulario cuando son válidos:
![]() | ![]() |
En comparación con la versión anterior, la novedad radica en el enlace [Retour au formulaire]. La vista se genera a partir de la página JSP [reponse.jsp] siguiente:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
// se recuperan los datos del modelo
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td><%= nom %>
</tr>
<tr>
<td>Age</td>
<td><%= age %>
</tr>
</table>
<br>
<a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
</body>
</html>
- línea 31: el enlace de vuelta al formulario. Este enlace tiene dos componentes:
- el destino [href="?action=retourFormulaire"]. La vista [réponse] se muestra tras la vista POST del formulario [formulaire.jsp] en la URL [/personne2/main]. Por lo tanto, es esta última URL la que se muestra en el navegador cuando se muestra la vista [réponse]. Al hacer clic en el enlace [Retour au formulaire], el navegador realizará una solicitud GET a la URL especificada por el atributo [href] del enlace, en este caso «?action=retourFormulaire». A falta de una URL en [href], el navegador utilizará la de la vista que se muestra actualmente, c.a.d. [/personne2/main]. En definitiva, al hacer clic en el enlace [Retour au formulaire], el navegador realizará una solicitud GET a la URL [/personne2/main?action=retourFormulaire], c.a.d, la URL del controlador de la aplicación, acompañada del parámetro [action] para indicarle qué debe hacer.
- El texto del enlace. Este formará parte de la plantilla enviada a la página por el controlador y recuperada en la línea 10.
6.4.3. La vista [erreurs]
Esta vista señala los errores de introducción de datos en el formulario:
![]() | ![]() |
En comparación con la versión anterior, la novedad radica en el enlace [Retour au formulaire]. La vista es generada por la página JSP [erreurs.jsp] siguiente:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page import="java.util.ArrayList" %>
<%
// se recuperan los datos del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
<%
for(int i=0;i<erreurs.size();i++){
out.println("<li>" + (String) erreurs.get(i) + "</li>\n");
}//para
%>
</ul>
<br>
<a href="?action=retourFormulaire"><%= lienRetourFormulaire %></a>
</body>
</html>
- línea 26: el enlace de vuelta al formulario. Este enlace es idéntico al de la vista [réponse]. Se recomienda al lector que, si lo considera necesario, vuelva a leer las explicaciones proporcionadas para esta vista.
6.5. Pruebas de las vistas
Para realizar las pruebas de las vistas anteriores, duplicamos sus páginas JSP en la carpeta /WebContent/JSP del proyecto Eclipse:

A continuación, en la carpeta JSP, se modifican las páginas de la siguiente manera:
[formulaire.jsp]:
...
<%
// -- prueba: se crea la plantilla de la página
session.setAttribute("nom","tintin");
session.setAttribute("age","30");
request.setAttribute("urlAction","main");
%>
<%
// se recuperan los datos de la plantilla
String nom=(String)session.getAttribute("nom");
String age=(String)session.getAttribute("age");
String urlAction=(String)request.getAttribute("urlAction");
%>
Se han añadido las líneas 4-5 para crear la plantilla que necesita la página de las líneas 11-13.
[reponse.jsp]:
<%
// -- prueba: se crea la plantilla de la página
request.setAttribute("nom","milou");
request.setAttribute("age","10");
request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>
<%
// se recuperan los datos de la plantilla
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
Se han añadido las líneas 4-6 para crear la plantilla que necesita la página de las líneas 11-13.
[erreurs.jsp]:
<%
// -- prueba: se crea la plantilla de la página
ArrayList<String> erreurs1=new ArrayList<String>();
erreurs1.add("erreur1");
erreurs1.add("erreur2");
request.setAttribute("erreurs",erreurs1);
request.setAttribute("lienRetourFormulaire","Retour au formulaire");
%>
<%
// se recuperan los datos de la plantilla
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
Se han añadido las líneas 4-8 para crear la plantilla que necesita la página de las líneas 13-14.
Iniciemos Tomcat, si aún no lo hemos hecho, y luego accedamos a las siguientes URL:
![]() | ![]() |
![]() |
Efectivamente, obtenemos las vistas esperadas.
6.6. El controlador [ServletPersonne]
El controlador [ServletPersonne] de la aplicación web [/personne2] gestionará las siguientes acciones:
n.º | solicitud | origen | tratamiento |
1 | [GET /personne2/main] | URL introducida por el usuario | - enviar la vista [formulaire] vacía |
2 | [POST /personne2/main] con parámetros [txtNom, txtAge, acción] enviados | al hacer clic en el botón [Envoyer] de la vista [formulaire] | - comprobar los valores de los parámetros [txtNom, txtAge] - si son incorrectos, enviar la vista [erreurs(erreurs)] - si son correctos, enviar la vista [reponse(nom,age)] |
3 | [GET /persona2/main? action=retourFormulaire] | haz clic en el enlace [Volver al formulario] de las vistas respuesta] y [erreurs]. | - Enviar la vista [formulaire] prellenada con los últimos valores introducidos |
Por lo tanto, tenemos una nueva acción que gestionar: [GET /personne2/main?action=retourFormulaire].
6.6.1. Estructura básica del controlador
La estructura del controlador [ServletPersonne] es prácticamente idéntica a la de la versión anterior:
Novedades:
- línea 4: el uso de una sesión obliga a importar el paquete [HttpSession]
- líneas 28-30: el nuevo método [doRetourFormulaire] gestiona la nueva acción: [GET /personne2/main?action=retourFormulaire].
6.6.2. Inicialización del controlador [init]
El método [init] es idéntico al de la versión anterior. Comprueba la presencia en el archivo [web.xml] de los elementos declarados en la tabla [paramètres]:
- línea 5: se han añadido los parámetros [urlControleur] (URL del controlador) y [lienRetourFormulaire] (texto del enlace de las vistas [réponse] y [erreurs]).
6.6.3. El método [doGet]
El método [doGet] debe gestionar la acción [GET /personne2/main?action=retourFormulaire], que antes no existía:
- líneas 6-14: se comprueba que la lista de errores de inicialización esté vacía. Si no es así, se muestra la vista [erreurs(erreursInitialisation)], que indicará el error o los errores.
Para entender este código, hay que recordar la plantilla de la vista [erreurs]:
<%
// se recuperan los datos del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
La vista [erreurs] espera un elemento clave «erreurs» en la consulta. El controlador crea este elemento en la línea 8. También espera un elemento clave «lienRetourFormulaire». El controlador crea este elemento en la línea 9. En este caso, el texto del enlace estará vacío. Por lo tanto, no habrá ningún enlace en la vista [erreurs] enviada. De hecho, si se han producido errores al inicializar la aplicación, esta debe reconfigurarse. No procede ofrecer al usuario la posibilidad de continuar con la aplicación a través de un enlace.
- líneas 34-37: procesamiento de la nueva acción [GET /personne2/main?action=retourFormulaire]
6.6.4. El método [doInit]
Este método procesa la solicitud n.º 1 [GET /personne2/main]. En esta solicitud, debe enviar la vista [formulaire(nom,age)] vacía. Su código es el siguiente:
- línea 4: se recupera la sesión actual si existe; de lo contrario, se crea (parámetro true de getSession).
- líneas 9-10: se muestra la vista [formulaire]. Recordemos la plantilla que espera esta vista:
<%
// se recuperan los datos del modelo
String nom=(String)session.getAttribute("nom");
String age=(String)session.getAttribute("age");
String urlAction=(String)request.getAttribute("urlAction");
%>
- líneas 6-7: los elementos [nom,age] del modelo de la vista [formulaire] se inicializan con cadenas vacías y se colocan en la sesión, ya que es ahí donde los espera la vista.
- línea 8: el elemento [urlAction] del modelo se inicializa con el valor del parámetro [urlControleur] del archivo [web.xml] y se coloca en la consulta.
6.6.5. El método [doValidationFormulaire]
Este método procesa la consulta n.º 2 [POST /personne2/main], en la que los parámetros enviados son [action, txtNom, txtAge]. Su código es el siguiente:
- líneas 5-6: se recuperan de la solicitud del cliente los valores de los parámetros «txtNom» y «txtAge».
- líneas 8-10: se almacenan estos valores en la sesión para poder recuperarlos cuando el usuario haga clic en el enlace [Retour au formulaire] de las vistas [réponse] y [erreurs].
- líneas 12-19: se comprueba la validez de los valores de los dos parámetros
- líneas 21-28: si alguno de los parámetros es erróneo, se muestra la vista [erreurs(erreurs,lienRetourFormulaire)]. Recordemos el modelo de esta vista:
<%
// se recuperan los datos del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
- líneas 30-34: si los dos parámetros «txtNom» y «txtAge» recuperados tienen valores válidos, se muestra la vista [reponse(nom,age,lienRetourFormulaire)]. Hay que recordar la plantilla de la vista [reponse]:
<%
// se recuperan los datos del modelo
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
String lienRetourFormulaire=(String)request.getAttribute("lienRetourFormulaire");
%>
6.6.6. El método [doRetourFormulaire]
Este método procesa la consulta n.º 3 [GET /personne2/main?action=retourFormulaire]. Su código es el siguiente:
Al finalizar este método, debe mostrarse la vista [formulaire] prellenada con las últimas entradas realizadas por el usuario. Recordemos la plantilla de la vista [formulaire]:
<%
// se recuperan los datos del modelo
String nom=(String)session.getAttribute("nom");
String age=(String)session.getAttribute("age");
String urlAction=(String)request.getAttribute("urlAction");
%>
Por lo tanto, el método [doRetourFormulaire] debe construir el modelo anterior.
- Línea 4: se recupera la sesión en la que el controlador ha almacenado los valores (nombre, edad) introducidos.
- línea 7: se recupera el nombre de la sesión
- líneas 8-9: si no está ahí, se introduce con un valor vacío. Este caso no debería darse en el funcionamiento normal de la aplicación, ya que la acción [retourFormulaire] siempre tiene lugar después de la acción [validationFormulaire], es decir, después de que los datos introducidos se hayan guardado en la sesión. Sin embargo, una sesión puede caducar, ya que tiene una duración limitada, a menudo de unas decenas de minutos. En este caso, la línea 4 ha creado una nueva sesión en la que no aparecerá el nombre. Por lo tanto, se introduce un nombre vacío en la nueva sesión.
- Líneas 11-13: se hace lo mismo con la edad
- Si se ignora el problema de la sesión caducada, las líneas 3-13 son innecesarias. Los elementos [nom,age] del modelo ya se encuentran en la sesión. Por lo tanto, no es necesario volver a introducirlos.
- línea 15: se establece el valor del elemento [urlAction] del modelo
6.7. Pruebas
Iniciar o reiniciar Tomcat. Acceder a la URL [http://localhost:8080/personne2] y, a continuación, repetir las pruebas que se muestran a modo de ejemplo en el apartado 6.1.
















