Computación Web (2023/24)

Práctica 5: Desarrollo de una aplicación Web con Spring MVC (I)

Preparación de tu entorno de desarrollo

El entorno de desarrollo recomendado para este laboratorio y los siguientes son los ordenadores de los laboratorios del Departamento de Ingeniería Telemática, a los que puedes acceder directamente en un laboratorio o de forma remota desde un navegador Web a través del servicio de laboratorio virtual en https://aulavirtual.lab.it.uc3m.es/. En ellos usaremos un sistema GNU/Debian Linux.

Cuando te conectes al servicio de laboratorio virtual, selecciona siempre que sea posible "DPTO-TELEM-VIRTUAL-4", ya que sus máquinas virtuales están siempre disponibles para acceso libre, mientras que las otras podrían estar reservadas para clases de otras asignaturas.

No obstante, puedes usar tu propio ordenador Linux, Windows o MacOS si lo prefieres. En ese caso, deberás instalar tú mismo un servidor de bases de datos MySQL o MariaDB (no debería ser demasiado complicado) así como un JDK de Java 17 o superior (por ejemplo, OpenJDK u Oracle JDK). Puedes usar Visual Studio Code o tu entorno de desarrollo preferido para Java. Por favor, ten en cuenta que es imposible para los profesores proporcionar soporte técnico para la instalación en tu propio ordenador de las herramientas necesarias u otros problemas relacionados.

Para tu comodidad, cada ejercicio proporcionará tanto los comandos Linux como los de Windows cuando sea apropiado. Los comandos Linux están adaptados para la instalación en el laboratorio, aunque probablemente funcionarán en otros sistemas Linux e incluso MacOS. De nuevo, ten en cuenta que no podemos garantizar que estos comandos funcionen correctamente si no estás usando los ordenadores del Departamento de Ingeniería Telemática en el laboratorio o los virtuales.

Despliegue de la base del proyecto

La aplicación que desarrollarás en el proyecto funcionará sobre el entorno Spring Boot, el cual facilitará considerablemente la tarea de desplegar un servidor Web en que ejecutar tu aplicación. Este entorno proporciona un sistema llamado Spring Initializr que permite crear el esqueleto inicial de una aplicación Spring Boot. Cuando quieras comenzar a desarrollar una aplicación Spring desde cero, resultará práctico utilizar este servicio.

Sin embargo, en vez de utilizar Initializr, comenzaremos este proyecto sobre la base de código que se proporciona a continuación. Crea un directorio de trabajo para el código del proyecto y, en él, descarga y descomprime el fichero microblog-app.tgz.

Antes de hacer nada más, puedes comprobar que el código base funcione entrando en el directorio microblog-app que se acaba de descomprimir y ejecutando el comando:

./gradlew bootRun

Si estás en Windows, ejecuta en su lugar:

gradlew bootRun

Tras cerca de un minuto (a partir de la segunda vez tardará bastante menos), la aplicación Web estará lista. Cuando dejen de actualizarse los mensajes y veas el texto "Started MicroblogApplication in X seconds", aunque no te indique un porcetaje del 100%, podrás acceder a la aplicación abriendo en un navegador el URL http://localhost:8080/. Deberías ver una página muy simple que solo muestra dos publicaciones de prueba.

Gradle es un sistema que automatiza la obtención de dependencias, compilación y despliegue de aplicaciones. En este caso, se encarga de descargar todas las bibliotecas de código que tu aplicación necesita, compilar el código fuente de la aplicación y lanzar un servidor Web a través del cual podrás acceder a la misma.

Puedes parar este servidor en cualquier momento introduciendo en el terminal la combinación de teclas Ctrl+C en el terminal en que estés ejecutando Gradle. En general, cada vez que cambies el código y desees probar los cambios, pararás el servidor y lo volverás iniciar, para que se compile y despliegue la nueva versión de la aplicación.

Análisis de la aplicación desplegada

Abre el directorio microblog-app desde tu entorno de desarrollo preferido. Por ejemplo, si usas Visual Studio Code, entra en el directorio y ejecuta (o, simplemente, ejecuta Visual Studio Code y selecciona el menú File / Open Folder):

code . &

Este primer inicio le puede llevar unos minutos hasta que todo esté listo. A partir de la segunda vez debería iniciar más rápidamente.

Antes de nada, instala las siguientes extensiones de Visual Studio Code, que facilitarán el desarrollo de aplicaciones Spring Boot en Java: Spring Boot Extension Pack y Java Extension Pack. Puedes instalarlas en el menú de extensiones de VS Code, buscándolas por nombre y presionando en el botón de instalación.

Encontrarás el código fuente Java de la aplicación Web bajo el directorio src/main/java. El primer fichero de la aplicación en el cual te puedes fijar es el código fuente de la clase que define la aplicación, MicroblogApplication en el paquete es.uc3m.microblog:

@SpringBootApplication
public class MicroblogApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicroblogApplication.class, args);
    }
}

Esta clase arranca el entorno de autoconfiguración que Spring Boot proporciona para la aplicación.

Cuando pides el recurso principal (URL /) de la aplicación, se ejecuta el método mainView del controlador MainController en el paquete es.uc3m.microblog.controllers:

@Controller
@RequestMapping(path = "/")
public class MainController {

    @GetMapping(path = "/")
    public String mainView(Model model) {
        List<Message> messages = new ArrayList<Message>();
        User user = new User();
        user.setId(1);
        user.setEmail("mary@example.com");
        user.setName("mary");
        Message message = new Message();
        message.setId(1);
        message.setUser(user);
        message.setText("Test post");
        message.setTimestamp(new Date());
        messages.add(message);
        message = new Message();
        message.setId(2);
        message.setUser(user);
        message.setText("Another post");
        message.setTimestamp(new Date());
        messages.add(message);
        model.addAttribute("messages", messages);
        return "main_view";
    }
}

Este controlador crea, a modo de demostración porque la aplicación todavía no está conectada con una base de datos, un usuario y dos publicaciones en la red social (observa el código de las clases User y Message en el paquete es.uc3m.microblog.model). A continuación, el programa añade una lista con las dos publicaciones creadas como atributo del objeto de la clase Model. Finalmente, devuelve la cadena de texto "main_view".

El hecho de devolver esta cadena de texto le indica al entorno que debe devolver al cliente la salida proporcionada por la plantilla de código src/main/resources/templates/main_view.html. El objeto Model será accesible a esta plantilla, lo cual le permitirá acceder a los objetos de ambos mensajes y, por tanto, mostrar su contenido. Observa el contenido de esta plantilla:

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Microblogging app</title>
        <link rel="stylesheet" href="public/microblog.css">
    </head>
    <body>
        <header>
            <h1>Microblogging</h1>
            <a href="/">Home</a>
        </header>
        <section class="content">
            <form th:action="@{/post}" method="post">
                <textarea name="text" placeholder="Type a new post here"></textarea>
                <input type="submit" value="Post!">
            </form>
            <h2>Latest posts from the people you follow</h2>
            <div class="messages">
                <div class="message" th:each="message : ${messages}">
                    <div class="text" th:text="${message.getText()}">
                        Text of the post
                    </div>
                    <div class="metadata">
                        <span class="author" th:text="${message.getUser().getName()}">Author's name</span>
                        <span class="date" th:text="${message.getTimestamp()}">Timestamp</span>
                    </div>
                </div>
            </div>
        </section>
    </body>
</html>

Esta plantilla se basa en el lenguaje de plantillas Thymeleaf. Este lenguaje te permite escribir código HTML estático para las vistas de tu aplicación, y añadirle instrucciones para inyectar en las plantillas datos provenientes de la aplicación. En este caso, se está accediendo al atributo messages que el controlador almacenó anteriormente en el objeto Model.

El elemento div de la clase message se generará tantas veces como publicaciones se incluyan en el atributo messages recibido. La variable llamada message irá tomando como valor cada uno de dichos mensajes y, por tanto, se irá mostrando el texto de los mensajes uno a uno a partir de la plantilla que se proporciona para este elemento div.

Modifica el controlador para que cree e incluya en la lista una nueva publicación. Para que tomen efecto las modificaciones que acabas de realizar, para la aplicación presionando Control+C en el terminal donde la estés ejecutando e iníciala de nuevo a continuación. Recarga la página en el navegador y comprueba que ahora se muestre también el mensaje que acabas de crear.

Plantilla de la vista principal

Integra la vista principal que creaste en el laboratorio de HTML y CSS, junto con su hoja de estilos CSS, con las plantillas del ejercicio anterior, de forma que se presenten los mismos tres mensajes con el aspecto que tendrán en tu aplicación.

Guarda los ficheros estáticos, como tus hojas de estilos CSS o imágenes, bajo el directorio src/main/resources/static/public en el árbol de directorios de tu código fuente. Su ruta URL comenzará por /public (observa, por ejemplo, cómo ya se está incluyendo una hoja de estilos CSS en main_view.html).

Vista del perfil público de un usuario

De forma análoga a lo hecho en la vista principal, crea un método controlador y una plantilla para la vista que muestra el perfil público de un usuario.

En primer lugar, debes crear un nuevo método en la clase MainController que cree un usuario de prueba, así como una lista con algunos mensajes de dicho usuario. Debes además asignarle una ruta distinta a la de la vista principal como, por ejemplo, /user.

A continuación, debes crear una nueva plantilla Thymeleaf que reciba el objeto usuario y los mensajes, y los muestre, reutilizando el diseño de esta vista que creaste en el laboratorio de HTML y CSS. Recuerda que el método del controlador debe devolver el nombre de esta nueva plantilla para que esta se aplique.

Plantilla de la vista de mensaje

De forma similar a la vista principal y a la vista del perfil público de un usuario, crea el controlador y la plantilla para la vista que muestra un mensaje concreto junto con las respuestas al mismo.

Primero, añade un nuevo método a la clase MainController que cree un mensaje de prueba, así como una lista con algunas respuestas (también de prueba) a dicho mensaje. Asígnale una ruta, como /message.

A continuación, debes crear una nueva plantilla Thymeleaf que muestre dichos objetos, con un diseño que sea consistente con las otras dos vistas que ya tienes.