Imprimir

La arquitectura Model 2 para el diseño de páginas JSP, es en realidad una arquitectura Modelo-Vista-Controlador (MVC), aplicado a las aplicaciones web. En este modelo de arquitectura se separa la salida que muestra el contenido, de la lógica usada para obtener y manipular el contenido.

Los pasos que sigue una aplicación que emplea este tipo de arquitectura puede ser similar a la siguiente. En ellos se muestra el camino recorrido por una petición enviada por el cliente desde el navegador, hasta que se recibe una página de respuesta con los datos obtenidos desde la base de datos.

  1. El Servlet controlador gestiona la petición recibida desde el cliente.
  2. Es posible el Servlet controlador utilice otras clases ayudantes que se encarguen de realizar otras operaciones de manipulación de los datos.
  3. Se obtienen los datos necesarios desde la base de datos.
  4. Los datos se manipulan utilizando un JavaBean con el modelo de datos.
  5. El Servlet controlador obtiene los datos en forma de objetos del JavaBean.
  6. Se envían los datos al código JSP que formará la vista.
  7. El código en JSP utiliza el modelo de datos para obtener las distintas propiedades del objeto.
  8. La ejecución del código JSP genera la salida que se envía al cliente.

 Java Model 2

A continuación se van a mostrar los códigos correspondientes a un proyecto de ejemplo que emplea esta arquitectura. Se trata de un proyecto muy básico en el que se va a simular una parte de la gestión de una agenda de contactos. La aplicación ofrecerá al usuario un formulario inicial donde podrá indicar el identificador del contacto que desea consultar. Una vez enviado ese identificador, se realizará la consulta correspondiente en la base de datos y el usuario obtendrá los datos del contacto solicitado.

Estructura y datos de ejemplo de la base de datos

El código SQL que se muestra a continuación permitirá crear en la base de datos la tabla contacto, con una serie de campos básicos (nombre, apellidos, teléfono, correo y un identificador numérico), y se añadirán 5 registros para las pruebas. Por tanto este código permitirá implementar la parte de la base de datos del esquema anterior:

Java Model 2 A 2549e

Ejecuta el siguiente script SQL en tu servidor MySQL, sobre una base de datos que se llame agendaDB.

CREATE TABLE contacto (
  nombre varchar(20) NOT NULL,
  apellidos varchar(50) NOT NULL,
  telefono varchar(15) NOT NULL,
  correo varchar(30) NOT NULL,
  id int(11) NOT NULL auto_increment,
  PRIMARY KEY  (id)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ;

INSERT INTO contacto VALUES ('AMADOR', 'OSSORIO MUÑOZ', '684402588', 'amaoss53 @ hotmail.com', 1);
INSERT INTO contacto VALUES ('BALTASAR', 'LORENTE  FERNANDEZ', '675435350', 'ballor65 @ hotmail.com', 2);
INSERT INTO contacto VALUES ('JESUS', 'PEDRO IGLESIAS ', '611932600', 'jesped87 @ hotmail.com', 3);
INSERT INTO contacto VALUES ('MARIA DOLORES', 'SAHELICES DOMINGUEZ', '675378525', 'marsah68 @ hotmail.com', 4);
INSERT INTO contacto VALUES ('ILUMINADA', 'LEON VICENTE', '614367425', 'iluleo71 @ yahoo.com', 5);

Proyecto Java Web en NetBeans

Crea en NetBeans un nuevo proyecto de tipo Java with Maven > Java Web Application.

Añade al proyecto la librería MySQL Connector Java. Para ello, abre el archivo pom.xml que puedes encontrar en la carpeta Project Files del proyecto y añade el siguiente código dentro de la sección <dependencies>:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

Al reconstruir el proyecto (Run > Clean and Build Project) se debe descargar esa librería y aparecer dentro de la carpeta Dependencies del proyecto.

JavaBean

En ese proyecto de NetBeans que acabas de crear, añade una nueva clase Java que deberás llamar Contacto. Esta clase corresponderá al JavaBean de los objetos que se han almacenado en la base de datos, por lo que deberá tener como propiedades cada uno de los campos de la tabla que se ha creado en la base de datos. Con es habitual en las clases JavaBean, se ha creado los métodos get y set para cada propiedad, así como un método constructor sin parámetros, y otro constructor con todos los datos requeridos para crear una objeto contacto completo.

Por tanto, este código corresponde al modelo de datos empleado por la aplicación en el esquema de la arquitectura:

Java Model 2 B 185ae

(El código indica que debe encontrarse en un paquete llamado agenda dentro del proyecto, si usas otro nombre de paquete cambia la primera línea)

package agenda;

public class Contacto {
    private String nombre;
    private String apellidos;
    private String telefono;
    private String correo;
    private int id;
    
    public Contacto() {        
    }

    public Contacto(String nombre, String apellidos, String telefono,
            String correo, int id) {
        this.nombre = nombre;
        this.apellidos = apellidos;
        this.telefono = telefono;
        this.correo = correo;
        this.id = id;
    }
    
    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getApellidos() {
        return apellidos;
    }

    public void setApellidos(String apellidos) {
        this.apellidos = apellidos;
    }

    public String getTelefono() {
        return telefono;
    }

    public void setTelefono(String telefono) {
        this.telefono = telefono;
    }

    public String getCorreo() {
        return correo;
    }

    public void setCorreo(String correo) {
        this.correo = correo;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
    
}

Controller Helper

Crea la siguiente clase Java con el nombre BDAgendaHelper. En esta clase se llevarán a cabo todas las operaciones sobre la base de datos. De esta manera se separa el código correspondiente al acceso a la base de datos del código asociado al resto de operaciones del proyecto.

Esta parte corresponde al Ayudante del controlador, como se mostraba en el esquema de la arquitectura:

Java Model 2 C e544b

Observa que en la línea donde se hace la conexión con la base de datos se debe indicar el nombre de usuario y la contraseña de acceso al servidor MySQL. Cambia esos datos por los que tengas asignados en tu base de datos.

package agenda;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class BDAgendaHelper {
    
    private static Connection conexion;
    
    public static boolean conectar() {
        try {
            // Declarar driver y conectar con la base de datos
            Class.forName("com.mysql.jdbc.Driver");
            conexion = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/agendaDB?serverTimezone=UTC", "usuario", "contraseña");
            return true;
        } catch(ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch(SQLException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    public static Contacto getContacto(String id) {
        if(conexion!=null) {
            try {
                // Crear la consulta SQL
                Statement st = conexion.createStatement();
                ResultSet rs = st.executeQuery("select * from contacto where id=" + id);
                
                // Comprobar si se ha obtenido algún resultado en la consulta
                if (rs.next()) {
                    // Crear un objeto a partir de los datos obtenidos en la consulta
                    Contacto contacto = new Contacto(rs.getString("nombre"),
                            rs.getString("apellidos"), rs.getString("telefono"),
                            rs.getString("correo"), rs.getInt("id") );
                    return contacto;
                }
            } catch(SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

Controller (Servlet)

La parte donde reside la parte principal de la lógica de la aplicación residirá en el Servlet. Esta clase Java se encarga de recibir la información enviada por el usuario (por ejemplo a través de un formulario como en este proyecto), realizar las acciones oportunas en función de esa información (como consultar la base de datos) y realizar la llamada al archivo JSP que generará la salida que se envía al usuario como respuesta.

Java Model 2 D 049d6

Crea un Servlet con nombre Consulta. Su contenido debe quedar con el siguiente código en el método processRequest:

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Recoger parámetros que ha enviado el usuario
        String idContacto = request.getParameter("id");
        String formato = request.getParameter("formato");
        
        // Conectar con la base de datos
        if(BDAgendaHelper.conectar()) {
            // Obtener el registro de la base de datos con el ID solicitado
            Contacto contacto = BDAgendaHelper.getContacto(idContacto);
            
            // Si se ha encontrado un contacto con el ID solicitado
            if(contacto!=null) {
// Asignar el objeto contacto como un atributo de la petición para hacerlo accesible desde el JSP request.setAttribute("contacto", contacto); // Realizar la petición de una página JSP u otra según el tipo de formato solicitado por el usuario if(formato!=null && formato.equalsIgnoreCase("XML")) { // Enviar el archivo contacto_xml.jsp como respuesta RequestDispatcher dispatcher = request.getRequestDispatcher("/contacto_xml.jsp"); dispatcher.forward(request, response); } else { // Enviar el archivo mostrar_contacto.jsp como respuesta RequestDispatcher dispatcher = request.getRequestDispatcher("/mostrar_contacto.jsp"); dispatcher.forward(request, response); } } else { // No se ha encontrado ningún contacto con ese ID PrintWriter out = response.getWriter(); out.println("No hay ningún contacto con el identificador "+idContacto); } } }

Página de inicio (index.html) con formulario para hacer la petición

Como se puede apreciar en el Servlet anterior, se van a recoger, de la llamada a dicho archivo, 2 parámetros que deben llamarse id y formato.

// Recoger parámetros que ha enviado el usuario
String idContacto = request.getParameter("id");
String formato = request.getParameter("formato");

Por tanto, se debe asegurar que cuando el usuario haga la llamada al Servlet Consulta se le envíe esa información. Para facilitarle la labor al usuario se va a crear un formulario HTML básico que hace la llamada al Servlet:

<form method="get" action="Consulta">

En 2 campos del formulario se solicita al usuario que introduzca el ID del contacto deseado y si desea obtener la respuesta en formato XML:

Id. Contacto: <input type="text" name="id"><br/>
Formato XML: <input type="checkbox" name="formato" value="xml"><br/>

El código completo de este formulario puede quedar como el siguiente. Escribe el código en el archivo index.html para que se el usuario accede directamente a este formulario:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Ejemplo Java Model 2 (Agenda de contactos)</title>
</head>
<body>
    <form method="get" action="Consulta">
        Id. Contacto: <input type="text" name="id"><br/>
        Formato XML: <input type="checkbox" name="formato" value="xml"><br/>
        <input type="submit" value="Enviar">
    </form>
</body>
</html>

Cuando pruebas el funcionamiento de este formulario verás en la barra de direcciones del navegador que se hace la llamada al Servlet indicando los valores de ambos parámetros. 

Si únicamente se indica el identificador del contacto a buscar, sin marcar la opción de formato XML se hace la siguiente llamada en el navegador:

Captura de pantalla 2021 01 10 a las 13.36.20 6602d

http://localhost/Consulta?id=1

En cambio, si se marca la opción de formato XML, la llamada incluye ese segundo parámetro:

Captura de pantalla 2021 01 10 a las 13.39.44 37aa0

http://localhost/Consulta?id=2&formato=xml

Así que este formulario se corresponde a la petición que se hace inicialmente desde el cliente dentro del esquema de esta arquitectura:

Java Model 2 E 73cd9

View (HTML) - mostrar_contacto.jsp

Como habrás podido ver, según el parámetro formato que ha recibido el Servlet, la respuesta al usuario se generará de dos maneras posibles. Este código JSP será invocado cuando el usuario no haya especificado nada en el formato.

Observa que se genera una respuesta en formato HTML con los datos del contacto que el Servlet había obtenido desde la base datos.

Con la siguiente línea se obtendrá el objeto contacto (de la clase Contacto que se encuentra en el paquete agenda). Ten en cuenta que si estás usando otro nombre de paquete en el proyecto deberás especificarlo en el nombre de la clase.

<jsp:useBean id="contacto" class="agenda.Contacto" scope="request" />

Recuerda que en el Servlet se usó la siguiente línea para pasar el objeto contacto (donde el Servlet ha almacenado los datos obtenidos previamente desde la base de datos), como un atributo llamado también "contacto" para los archivos JSP. Por eso se indica id="contacto" en el código JSP.

request.setAttribute("contacto", contacto);

Para que el archivo JSP muestre los datos del contacto se usarán líneas como:

<jsp:getProperty name="contacto" property="apellidos" />

Así quedará el archivo JSP completo:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Datos del contacto</title>
</head>
<body>
    <h1>Datos del contacto</h1>
    <jsp:useBean id="contacto" class="agenda.Contacto" scope="request" />
    <b>Nombre:</b> <jsp:getProperty name="contacto" property="nombre" /> <br/><!-- También valdría con ${contacto.nombre} -->
    <b>Apellidos:</b> <jsp:getProperty name="contacto" property="apellidos" /> <br/>
    <b>Teléfono:</b> <jsp:getProperty name="contacto" property="telefono" /> <br/>
    <b>Correo:</b> <jsp:getProperty name="contacto" property="correo" /> <br/>
</body>
</html>

View (XML) - contacto_xml.jsp

De manera similar se puede generar una salida de los datos en formato XML:

<?xml version="1.0" encoding="UTF-8"?>
<%@ page language="java" contentType="text/xml; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
<jsp:useBean id="contacto" class="com.ejemplo.agenda.Contacto" scope="request" />
<contacto>
    <nombre><jsp:getProperty name="contacto" property="nombre" /></nombre>
    <apellidos><jsp:getProperty name="contacto" property="apellidos" /></apellidos>
    <telefono><jsp:getProperty name="contacto" property="telefono" /></telefono>
    <correo><jsp:getProperty name="contacto" property="correo" /></correo>
</contacto>

Estos archivos JSP se corresponden con la salida (vista) que se ofrece al cliente como respuesta a la petición:

Java Model 2 F 21b3d