5. Aplicación web MVC [personne] – versión 1
5.1. Las vistas de la aplicación
La aplicación retoma el formulario utilizado en los ejemplos anteriores. La primera página de la aplicación es la siguiente:

A esta vista la llamaremos [formulaire]. Si se introducen los datos correctamente, estos se muestran en una vista que se denominará [réponse]:

Si los datos introducidos son incorrectos, los errores se señalan en una vista denominada [erreurs]:

5.2. Arquitectura de la aplicación
La aplicación web [personne1] tendrá la siguiente arquitectura:

Esta arquitectura es de un solo nivel: no hay capas [métier] ni [dao], solo una capa [web]. [ServletPersonne] es el controlador de la aplicación que gestiona todas las solicitudes de los clientes. Para responder a ellas, utiliza una de las tres vistas [formulaire, réponse, erreurs].
Tenemos que determinar cómo el controlador [ServletPersonne] decide qué acción debe realizar al recibir una solicitud de un usuario. Una solicitud de cliente es un flujo HTTP que varía en función de si se realiza con un comando GET o POST.
Solicitud GET
En este caso, el flujo HTTP tiene el siguiente aspecto:
La línea 1 especifica la URL solicitada, por ejemplo:
Esta URL se puede utilizar para especificar la acción que se debe realizar. Se pueden emplear varios métodos:
- un parámetro de la URL especifica la acción, por ejemplo, [/appli?action=ajouter&id=4]. En este caso, el parámetro [action] indica al controlador la acción que se le solicita.
- el último elemento de la URL especifica la acción, por ejemplo, [/appli/ajouter?id=4]. En este caso, el controlador utiliza el último elemento de la URL [/ajouter] para determinar la acción que debe realizar.
Existen otras soluciones posibles. Las dos anteriores son las más habituales.
Solicitud POST
En este caso, el flujo HTTP tiene el siguiente aspecto:
La línea 1 especifica la URL solicitada, por ejemplo:
Esta URL se puede utilizar para especificar la acción que se debe realizar, como en el caso de GET. En el caso de GET, el parámetro [action] estaba integrado en URL. Esto también puede ser el caso aquí, como en:
Pero el parámetro [action] también puede estar incluido en los parámetros enviados (línea 15 anterior), como en:
A continuación, utilizaremos estas diferentes técnicas para indicar al controlador lo que debe hacer:
- incluir el parámetro action en la URL solicitada:
- enviar el parámetro action:
- utilizar el último elemento de la URL como nombre de la acción:
5.3. El proyecto Eclipse
Para crear el proyecto Eclipse [mvc-personne-01] de la aplicación web [personne1], se seguirá el procedimiento descrito en el apartado 3.1.

No se mantendrá el contexto [mvc-personne-01] propuesto por defecto. Se elegirá [personne1] tal y como se indica a continuación:

El resultado obtenido es el siguiente:

Si, por casualidad, se desea cambiar el contexto de la aplicación web, se utilizará la opción [clic droit sur projet -> Properties -> J2EE]:

Se indicará el nuevo contexto en [1].
Vamos a crear una subcarpeta [vues] dentro de la carpeta [WEB-INF]: [clic droit sur WEB-INF -> New -> Folder]:
![]() | ![]() |
El nuevo proyecto es ahora este:

Una vez completado, el proyecto quedará así:

- El controlador [ServletPersonne] se encuentra en la carpeta [src]
- Las páginas JSP de las vistas [formulaire, réponse, erreurs] se encuentran en la carpeta [WEB-INF/vues], lo que impide que el usuario las solicite directamente, tal y como se muestra en el ejemplo siguiente:

A continuación describimos los diferentes componentes de la aplicación web [/personne1]. Se invita al lector a crearlos a medida que avanza en la lectura.
5.4. Configuración de la aplicación web [personne1]
El archivo web.xml de la aplicación /personne1 tendrá el siguiente contenido:
<?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-01</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>
</servlet>
<!-- Asignación ServletPersonne-->
<servlet-mapping>
<servlet-name>personne</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<!-- archivos de inicio -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
¿Qué indica este archivo de configuración?
- líneas 34-37: el archivo URL /main es procesado por el servlet denominado «persona»
- líneas 10-13: el servlet denominado «persona» es una instancia de la clase [ServletPersonne]
- líneas 14-19: definen un parámetro de configuración denominado «[urlReponse]». Se trata de la URL de la vista «[réponse]».
- líneas 20-25: definen un parámetro de configuración denominado «[urlErreurs]». Es la URL de la vista «[erreurs]».
- Líneas 26-31: definen un parámetro de configuración denominado [urlFormulaire]. Es la URL de la vista [formulaire].
- Línea 40: [index.jsp] será la página de inicio de la aplicación.
Las URL de las páginas JSP de las vistas [formulaire, réponse, erreurs] son objeto, cada una, de un parámetro de configuración. Esto permite moverlas sin tener que recompilar la aplicación.
Cuando el usuario solicite la URL [/personne1], será el archivo [index.jsp] el que envíe la respuesta (archivo de inicio, línea 40). Este archivo se encuentra en la raíz de la carpeta [WebContent]:

Su contenido es el 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">
<%
response.sendRedirect("/personne1/main");
%>
La página [index.jsp] se limita a redirigir al cliente a la URL [/personne1/main]. Así, cuando el navegador solicita la URL [/personne1], [index.jsp] le envía la siguiente respuesta HTTP:
- línea 1: respuesta HTTP/1.1 para indicar al servidor que redirija a otra URL
- línea 4: la URL a la que debe redirigirse el navegador
Tras esta respuesta, el navegador solicitará la URL [/personne1/main] tal y como se le indica (línea 4). El archivo [web.xml] de la aplicación [/personne1] indica que esta solicitud será gestionada por el controlador [ServletPersonne] (líneas 35-36).
5.5. El código de las vistas
Comenzamos a escribir la aplicación web por las vistas. Estas permiten definir las necesidades del usuario en cuanto a la interfaz gráfica y pueden probarse sin necesidad de que el controlador esté presente.
5.5.1. La vista [formulaire]
Esta vista corresponde al formulario de introducción del nombre y la edad:

tipo HTML | nombre | función | |
<input type="text"> | txtNom | introducción del nombre | |
<input type="text"> | txtAge | Introducción de la edad | |
<input type="submit"> | Envío de los valores introducidos al servidor a la URL /persona1/main | ||
<input type="reset"> | para restablecer la página al estado en el que la recibió inicialmente el navegador | ||
<input type="button"> | para borrar el contenido de los campos de entrada [1] y [2] |
La genera la página JSP [formulaire.jsp]. Su plantilla está compuesta por los siguientes elementos:
- [nom]: un nombre (cadena) que se encuentra en los atributos de sesión asociados a la clave «nombre»
- [age]: una edad (cadena de caracteres) que se encuentra en los atributos de sesión asociados a la clave «edad»
La vista [formulaire] se obtiene cuando el usuario solicita la URL [/personne1/main], c.a.d, la URL del controlador [ServletPersonne]. El código de la página JSP [formulaire.jsp] que genera la vista [formulaire] es el 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");
%>
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form 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>
- líneas 6-7: la página JSP comienza recuperando de la solicitud [request] los elementos [nom, age] de su modelo. En el funcionamiento normal de la aplicación, será el controlador [ServletPersonne] el que construya esta plantilla.
- líneas 18-38: la página JSP generará un formulario HTML (etiqueta <form>)
- línea 18: la etiqueta <form> no tiene el atributo action para indicar la URL que deberá procesar los valores enviados mediante el botón [Envoyer] de tipo submit (línea 32). Los valores del formulario se enviarán entonces a la URL desde la que se obtuvo el formulario, es decir, la URL del controlador [ServletPersonne]. De este modo, este se utiliza tanto para generar el formulario vacío solicitado inicialmente por un GET como para procesar los datos introducidos que se le enviarán mediante el botón [Envoyer].
- Los valores enviados son los de los campos HTML, [txtNom] (línea 22), [txtAge] (línea 26) y [action] (línea 37). Este último parámetro permitirá al controlador saber qué debe hacer.
- Al mostrarse el formulario por primera vez, los campos de entrada [txtNom, txtAge] se inicializan, respectivamente, con las variables [nom] (línea 22) y [age] (línea 26). Estas variables obtienen los valores de sus atributos de la consulta (líneas 6-7), atributos que sabemos que son inicializados por el servlet. Por lo tanto, es este último el que establece el contenido inicial de los campos de entrada del formulario.
- línea 33: el botón [Rétablir], de tipo [reset], permite restablecer el formulario al estado en el que se encontraba cuando el navegador lo recibió.
- línea 34: el botón [Effacer], de tipo [reset], no tiene por el momento ninguna función.
En adelante, nos referiremos a esta vista como la vista [formulaire(nom, age)] cuando queramos especificar tanto el nombre de la vista como su modelo. Por otra parte, recordaremos que cuando el usuario hace clic en el botón [Envoyer], los parámetros [txtNom, txtAge] se envían a la URL [/personne1/main].
5.5.2. La vista [reponse]
Esta vista muestra los valores introducidos en el formulario cuando son válidos:

Se genera a partir de la página JSP [reponse.jsp]. Su plantilla está compuesta por los siguientes elementos:
- [nom]: un nombre (cadena de caracteres) que se encontrará en los atributos de sesión, asociado a la clave «nombre»
- [age]: una edad (cadena de caracteres) que se encontrará en los atributos de sesión, asociada a la clave «edad»
El código de la página JSP [reponse.jsp] es el 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");
%>
<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>
</body>
</html>
- líneas 6-7: la página JSP comienza recuperando de la solicitud [request] los elementos [nom, age] de su modelo. En el funcionamiento normal de la aplicación, será el controlador [ServletPersonne] el que construya esta plantilla.
- A continuación, los elementos [nom, age] del modelo se muestran en las líneas 20 y 24
A continuación, denominamos a esta vista «[réponse(nom, age)]».
5.5.3. La vista [erreurs]
Esta vista señala los errores de introducción de datos en el formulario:

Se genera a partir de la página JSP [erreurs.jsp]. Su plantilla está compuesta por los siguientes elementos:
- [erreurs]: una lista (ArrayList) de mensajes de error que se encontrará en los atributos de la consulta, asociada a la clave «errores»
El código de la página JSP [erreurs.jsp] es el 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");
%>
<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>
</body>
</html>
- línea 8: la página JSP comienza recuperando, de la consulta [request], el elemento [erreurs] de su modelo. Este elemento representa un objeto de tipo ArrayList compuesto por elementos de tipo String. Estos elementos son mensajes de error. En el funcionamiento normal de la aplicación, será el controlador [ServletPersonne] el que construya este modelo.
- Líneas 18-22: muestran la lista de mensajes de error. Para ello, hay que escribir código Java en el cuerpo HTML de la página. Siempre hay que intentar reducirlo al mínimo para no saturar el código HTML. Más adelante veremos que existen soluciones que permiten reducir la cantidad de código Java en las páginas JSP.
- Línea 4: cabe destacar la etiqueta de importación de los paquetes necesarios para la página JSP
A continuación, llamamos a esta vista «[erreurs(erreurs)]».
5.6. Pruebas de las vistas
Es posible comprobar la validez de las páginas JSP sin haber escrito el controlador. Para ello, se deben cumplir dos condiciones:
- hay que poder solicitarlas directamente a la aplicación sin pasar por el controlador
- la página JSP debe inicializar por sí misma el modelo que, normalmente, construiría el controlador
Para realizar estas pruebas, duplicamos las páginas JSP de las vistas 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
request.setAttribute("nom","tintin");
request.setAttribute("age","30");
%>
<%
// se recuperan los datos de la plantilla
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<html>
<head>
...
Se han añadido las líneas 3-7 para crear la plantilla que necesita la página de las líneas 11-12.
[reponse.jsp]:
...
<%
// -- prueba: se crea la plantilla de la página
request.setAttribute("nom","milou");
request.setAttribute("age","10");
%>
<%
// se recuperan los datos de la plantilla
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
<html>
<head>
...
Se han añadido las líneas 3-7 para crear la plantilla que necesita la página de las líneas 11-12.
[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);
%>
<%
// se recuperan los datos de la plantilla
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
%>
<html>
<head>
...
Se han añadido las líneas 3-9 para crear la plantilla que necesita la página de la línea 13.
Inicia Tomcat, si aún no lo has hecho, y a continuación solicita las siguientes URL:
![]() | ![]() |
![]() |
Efectivamente, obtenemos las vistas esperadas. Ahora que tenemos una confianza razonable en las páginas JSP de la aplicación, podemos pasar a escribir su controlador [ServletPersonne].
5.7. El controlador [ServletPersonne]
Aún nos queda por escribir el núcleo de nuestra aplicación web: el controlador. Su función consiste en:
- recoger la solicitud del cliente,
- procesar la acción solicitada por este,
- enviar como respuesta la vista adecuada.
El controlador [ServletPersonne] gestionará las siguientes acciones:
n.º | solicitud | origen | procesamiento |
1 | [GET /personne1/main] | URL introducida por el usuario | - enviar la vista [formulaire] vacía |
2 | [POST /personne1/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)] |
La aplicación se inicia cuando el usuario solicita la URL [/personne1/main]. Según el archivo [web.xml] de la aplicación (véase el apartado 5.4), esta solicitud es procesada por una instancia de tipo ServletPersonne que describimos a continuación.
5.7.1. Estructura básica del controlador
El código del controlador [ServletPersonne] es el siguiente:
- líneas 20-22: el método [init] que se ejecuta al cargarse inicialmente el servlet
- líneas 25-28: el método [doGet], invocado por el servidor web cuando se ha realizado una solicitud de tipo GET a la aplicación
- líneas 42-46: el método [doPost], invocado por el servidor web cuando se ha realizado una solicitud de tipo POST a la aplicación. Como se muestra, esta también será procesada por el método [doGet] (línea 45).
- líneas 31-33: el método [doInit] procesa la acción n.º 1 [GET /personne1/main]
- líneas 36-39: el método [doValidationFormulaire] procesa la acción n.º 2 [POST /personne1/main] con los parámetros enviados [txtNom, txtAge, action].
A continuación describimos los distintos métodos del controlador
5.7.2. Inicialización del controlador
Cuando el contenedor de servlets carga la clase del controlador, se ejecuta su método [init]. Esto solo ocurrirá una vez. Una vez cargado en memoria, el controlador permanecerá allí y procesará las solicitudes de los distintos clientes. Cada cliente cuenta con un hilo de ejecución propio, por lo que los métodos del controlador se ejecutan simultáneamente en diferentes hilos. Cabe recordar que, por este motivo, el controlador no debe tener campos que sus métodos puedan modificar. Sus campos deben ser de solo lectura. Se inicializan mediante el método [init], cuya función principal es precisamente esa. De hecho, este método tiene la particularidad de ejecutarse una única vez por un solo hilo. Por lo tanto, no hay problemas de acceso concurrente a los campos del controlador en este método. El método [init] tiene como objetivo inicializar los objetos necesarios para la aplicación web, que serán compartidos en modo de solo lectura por todos los hilos de cliente. Estos objetos compartidos pueden colocarse en dos lugares:
- los campos privados del controlador
- el contexto de ejecución de la aplicación (ServletContext)
El código del método [init] del controlador [ServletPersonne] es el siguiente:
- línea 16: se recupera la configuración de la aplicación web, c.a.d. El contenido del archivo [web.xml]
- líneas 19-29: se recuperan los parámetros de inicialización del servlet, cuyos nombres se definen en la tabla [paramètres] de la línea 9
- línea 21: se recupera el valor del parámetro
- línea 25: si el parámetro no existe, el error se añade a la lista de errores [erreursInitialisation], inicialmente vacía (línea 8).
- línea 28: si el parámetro está presente, se almacena junto con su valor en el diccionario [params], inicialmente vacío (línea 10).
- líneas 31-35: el parámetro [urlErreurs] debe estar presente obligatoriamente, ya que designa la URL de la vista [erreurs] capaz de mostrar los posibles errores de inicialización. Si no existe, se interrumpe la aplicación lanzando un [ServletException] (línea 33).
5.7.3. El método [doGet]
El método [doGet] gestiona tanto las solicitudes GET como las POST en el servlet, ya que el método [doPost] redirige al método [doGet]. Su código es el siguiente:
- líneas 18-25: 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 el modelo de la vista [erreurs]:
<%
// se recuperan los datos del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
%>
La vista [erreurs] espera un elemento clave «errores» en la solicitud. El controlador crea este elemento en la línea 20.
- Línea 28: se recupera el método [get] o [post] que el cliente ha utilizado para realizar su consulta
- línea 30: se recupera el valor del parámetro [action] de la consulta. Recordemos que, en nuestra aplicación, solo la solicitud n.º 2, [POST /personne1/main], tiene el parámetro [action]. En esta solicitud, tiene el valor [validationFormulaire].
- líneas 31-34: si el parámetro [action] no está presente, se le asigna el valor «init». Este será el caso en la solicitud inicial n.º 1, [GET /personne1/main].
- líneas 36-40: procesamiento de la solicitud n.º 1 [GET /personne1/main].
- líneas 41-45: procesamiento de la solicitud n.º 2 [POST /personne1/main].
- línea 47: si no se da ninguno de los dos casos anteriores, se procede como si se tratara del caso n.º 1
5.7.4. El método [doInit]
Este método procesa la solicitud n.º 1 [GET /personne1/main]. En esta solicitud, debe enviar la vista [formulaire(nom,age)] vacía. Su código es el siguiente:
- líneas 18-19: se muestra la vista [formulaire]. Recordemos el modelo que espera esta vista:
<%
// se recuperan los datos del modelo
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
- líneas 16-17: el modelo [nom,age] de la vista [formulaire] se inicializa con cadenas vacías.
5.7.5. El método [doValidationFormulaire]
Este método procesa la solicitud n.º 2 [POST /personne1/main], en la que los parámetros enviados son [action, txtNom, txtAge]. Su código es el siguiente:
- líneas 16-17: se recuperan de la solicitud del cliente los valores de los parámetros «txtNom» y «txtAge».
- líneas 19-26: se comprueba la validez de estos dos parámetros
- líneas 28-33: si alguno de los parámetros es erróneo, se muestra la vista [erreurs(erreursAppel)]. Recordemos el modelo de esta vista:
<%
// se recuperan los datos del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
%>
- líneas 35-38: si los dos parámetros «txtNom» y «txtAge» recuperados tienen valores válidos, se muestra la vista [reponse(nom,age)]. 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");
%>
5.8. Pruebas
Incluimos el proyecto [mvc-personne-01] en las aplicaciones de Tomcat siguiendo el procedimiento descrito en el apartado 3.3:

Inicie Tomcat. Una vez hecho esto, podremos retomar las pruebas que se muestran a modo de ejemplo en el apartado 5.1. También podremos añadir otras. Por ejemplo, podemos eliminar uno de los parámetros de configuración urlXXX de web.xml y ver el resultado. Así, como se muestra a continuación, uno de los parámetros se ha comentado en [web.xml]:
<!--
<init-param>
<param-name>urlFormulaire</param-name>
<param-value>
/WEB-INF/vues/formulaire.jsp
</param-value>
</init-param>
-->
Iniciamos o reiniciamos Tomcat y accedemos a la URL [http://localhost:8080/personne1/main]. Obtenemos la siguiente respuesta:





