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

Llamaremos a esta vista «[formulaire]». Si se ingresan los datos correctamente, estos se muestran en una vista que se llamará «[réponse]»:

Si las entradas son incorrectas, los errores se señalan en una vista llamada [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 procesa todas las solicitudes de los clientes. Para responder a estas, utiliza una de las tres vistas [formulaire, réponse, erreurs].
Debemos 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 según se realice con un comando GET o POST.
Solicitud GET
En este caso, el flujo HTTP se ve así:
La línea 1 especifica la URL solicitada, por ejemplo:
Se puede usar esta URL para especificar la acción a realizar. Se pueden utilizar diversos métodos:
- un parámetro de la URL especifica la acción, por ejemplo, [/appli?action=ajouter&id=4]. Aquí, el parámetro [action] le 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]. Aquí, 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 comunes.
Solicitud POST
En este caso, el flujo HTTP se ve así:
La línea 1 especifica la URL solicitada, por ejemplo:
Se puede utilizar esta URL para especificar la acción a 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 arriba) como en:
A continuación, utilizaremos estas diferentes técnicas para indicarle al controlador qué debe hacer:
- incorporar 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 de Eclipse [mvc-personne-01] de la aplicación web [personne1], se seguirá el procedimiento descrito en el párrafo 3.1.

No se mantendrá el contexto [mvc-personne-01] propuesto por defecto. Se elegirá [personne1] 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 ahora es 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, como se muestra en el siguiente ejemplo:

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 /persona1 será 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-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é dice este archivo de configuración?
- líneas 34-37: el archivo URL /main es procesado por el servlet llamado persona
- líneas 10-13: el servlet llamado «persona» es una instancia de la clase [ServletPersonne]
- líneas 14-19: definen un parámetro de configuración llamado [urlReponse]. Es la URL de la vista [réponse].
- líneas 20-25: definen un parámetro de configuración llamado [urlErreurs]. Es la URL de la vista [erreurs].
- Líneas 26-31: definen un parámetro de configuración llamado [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] simplemente redirige 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 se 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 como se le indica (línea 4). El archivo [web.xml] de la aplicación [/personne1] indica que esta solicitud será procesada por el controlador [ServletPersonne] (líneas 35-36).
5.5. El código de las vistas
Comenzamos a desarrollar la aplicación web escribiendo primero sus 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 para ingresar el nombre y la edad:

tipo HTML | nombre | función | |
<input type="text"> | txtNom | ingreso del nombre | |
<input type="text"> | txtAge | ingresar la edad | |
<input type="submit"> | Envío de los valores ingresados 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] |
Es generada por 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, en la consulta [request], los elementos [nom, age] de su modelo. En el funcionamiento normal de la aplicación, será el controlador [ServletPersonne] el que construya este modelo.
- 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 por 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 ingresados 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 le 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 ninguna función por el momento.
De ahora 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 ingresados en el formulario cuando estos son válidos:

Es generada por la página JSP [reponse.jsp]. Su plantilla consta de 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 este modelo.
- Los elementos [nom, age] del modelo se muestran luego en las líneas 20 y 24
Posteriormente, llamamos a esta vista la vista [réponse(nom, age)].
5.5.3. La vista [erreurs]
Esta vista señala los errores de entrada en el formulario:

Es generada por la página JSP [erreurs.jsp]. Su modelo está compuesto 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 que contiene 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, es necesario escribir código Java en el cuerpo HTML de la página. Siempre se debe procurar 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
Posteriormente, llamamos a esta vista, la vista [erreurs(erreurs)].
5.6. Pruebas de las vistas
Es posible probar la validez de las páginas JSP sin haber escrito el controlador. Para ello, se deben cumplir dos condiciones:
- se deben poder solicitar directamente a la aplicación sin pasar por el controlador
- la página JSP debe inicializar por sí misma el modelo que, normalmente, sería construido por el controlador
Para realizar estas pruebas, duplicamos las páginas JSP de las vistas en la carpeta [/WebContent/JSP] del proyecto de Eclipse:

Luego, en la carpeta JSP, las páginas se modifican 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 agregaron las líneas 3 a 7 para crear la plantilla que necesita la página de las líneas 11 y 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 agregaron las líneas 3 a 7 para crear la plantilla que necesita la página de las líneas 11 a 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 del modelo
ArrayList erreurs=(ArrayList)request.getAttribute("erreurs");
%>
<html>
<head>
...
Se agregaron las líneas 3 a 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 luego 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 corazón de nuestra aplicación web: el controlador. Su función consiste en:
- recibir la solicitud del cliente,
- procesar la acción solicitada por este,
- enviar como respuesta la vista correspondiente.
El controlador [ServletPersonne] procesará las siguientes acciones:
n.º | solicitud | origen | procesamiento |
1 | [GET /personne1/main] | URL ingresada por el usuario | - enviar la vista [formulaire] vacía |
2 | [POST /personne1/main] con parámetros [txtNom, txtAge, acción] publicados | al hacer clic en el botón [Envoyer] de la vista [formulaire] | - verificar 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 párrafo 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 cargar inicialmente el servlet
- líneas 25-28: el método [doGet], al que recurre el servidor web cuando se realiza una solicitud de tipo GET a la aplicación
- líneas 42-46: el método [doPost] es invocado por el servidor web cuando se realiza 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 diferentes 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 ocurrirá una sola 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 esta razón, el controlador no debe tener campos que sus métodos puedan modificar. Sus campos deben ser de solo lectura. Son inicializados por el método [init], cuya función principal es precisamente esa. De hecho, este método tiene la particularidad de ejecutarse una sola vez por un único 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, los cuales serán compartidos en modo de solo lectura por todos los hilos de los clientes. Estos objetos compartidos pueden ubicarse 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 agrega a la lista de errores [erreursInitialisation], que inicialmente está vacía (línea 8).
- línea 28: si el parámetro está presente, se almacena junto con su valor en el diccionario [params], que inicialmente está vacío (línea 10).
- líneas 31-35: el parámetro [urlErreurs] debe estar presente obligatoriamente, ya que indica la URL de la vista [erreurs] capaz de mostrar los posibles errores de inicialización. Si no existe, se interrumpe la aplicación ejecutando un [ServletException] (línea 33).
5.7.3. El método [doGet]
El método [doGet] procesa 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 verifica 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 utilizó 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 consulta 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 trata de 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]. Para 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 esperado por 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 verifica la validez de estos dos parámetros
- líneas 28-33: si alguno de los parámetros es incorrecto, 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 el modelo de la vista [reponse]:
<%
// se recuperan los datos del modelo
String nom=(String)request.getAttribute("nom");
String age=(String)request.getAttribute("age");
%>
5.8. Tests
Incluyamos el proyecto [mvc-personne-01] en las aplicaciones de Tomcat siguiendo el procedimiento descrito en el párrafo 3.3:

Inicie Tomcat. Una vez hecho esto, podremos retomar las pruebas mostradas como ejemplo en el párrafo 5.1. También podremos agregar otras. Por ejemplo, podemos eliminar uno de los parámetros de configuración de urlXXX en 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:





