5 - Pasos para crear una aplicación con Spring Boot elemental que sirva páginas dinámica - MVC y Service

La siguiente refactorización del proyecto anterior es el agregado de un módulo de servicios (Service).

El patrón MVC (Modelo-Vista-Controlador) no incluye explícitamente la capa de Servicios (Services). Sin embargo, en muchas implementaciones de MVC, especialmente en Spring Boot, se utiliza una capa de Servicios para manejar la lógica de negocio de la aplicación.

Problema

Rehacer el problema que muestra el chiste en una página web al azar. Organizar el código mediante el patrón MVC, agregando la lógica de negocios en una capa de servicios (Service)

Creación aplicación con el patrón MVC y Service

Los pasos para crear el proyecto:

  • Desde el menú de opciones seleccionamos File-> New -> Spring Starter Proyect:

    Creación aplicación MVC
  • En el primer diálogo procedemos a definir el nombre de nuestro proyecto. Utilizaremos Maven como herramienta de gestión de proyecto.

    Creación aplicación que sirve páginas dinámicas
  • En el segundo diálogo seleccionamos las dependencias "Spring Web" y "Thymeleaf"

    Selección de la dependencia Spring Web y Thymeleaf
  • Ahora en el paquete 'com.example.demo' procedemos a crear la carpeta 'model' presionando el botón derecho del mouse y definiendo como su nombre 'model'.

    En la carpeta model procedemos a crear la clase Chiste de forma idéntica como hicimos en el proyecto anterior.

    El código de la clase Chiste es el siguiente:

    package com.example.demo.model;
    
    public class Chiste {
        private String texto;
    
        public Chiste(String texto) {
            this.texto = texto;
        }
    
        public String getTexto() {
            return texto;
        }
    
        public void setTexto(String texto) {
            this.texto = texto;
        }
    }
    
  • Ahora lo nuevo con respecto al proyecto anterior consiste en crear el servicio. Procedemos a presionar con el botón derecho del mouse el paquete 'com.example.demo' y crear la carpeta 'service'

    Crear carpeta service

    Y en el diálogo procedemos a indicar el nombre 'service' (es una convención comúnmente adoptada):

    Crear carpeta service
  • En la carpeta service procedemos a crear la clase ChisteService:

    Creación de la clase ChisteService

    Y en el diálogo procedemos a indicar el nombre ChisteService:

    Crear la clase ChisteService

    El código de la clase ChisteService es el siguiente:

    package com.example.demo.service;
    
    import com.example.demo.model.Chiste;
    import org.springframework.stereotype.Service;
    import java.util.ArrayList;
    import java.util.List;
    
    @Service
    public class ChisteService {
    
        private List<Chiste> chistes;
    
        public ChisteService() {
            chistes = new ArrayList<>();
            chistes.add(new Chiste("¿Qué le dice un 0 a un 8? Bonito cinturón."));
            chistes.add(new Chiste("¿Qué hace una abeja en el gimnasio? ¡Zum-ba!"));
            chistes.add(new Chiste("¿Cuál es el colmo de un electricista? Que su hijo sea un apagado."));
            chistes.add(new Chiste("¿Por qué estás hablando con la pared? ¡Porque la mesa no me responde!"));
        }
    
        public Chiste obtenerChisteAleatorio() {
            return chistes.get((int) (Math.random() * chistes.size()));
        }
    }
    

    La anotación @Service en Spring es una de las varias anotaciones que se utilizan para definir los componentes de una aplicación.

    Un componente de servicio en Spring generalmente se utiliza para alojar la lógica de negocio de la aplicación.

    Proporcionan una capa de abstracción entre los controladores (o componentes que interactúan directamente con las solicitudes HTTP) y la capa de acceso a datos (más adelante veremos como acceder a una base de datos donde rescatar los chistes)

    Los servicios son inyectados en otras clases de la aplicación, como controladores, otros servicios, o componentes de configuración.

    La inyección de dependencias (Dependency Injection, DI) es un patrón de diseño fundamental en Spring Boot. La inyección de dependencias es un mecanismo que se utiliza para gestionar las dependencias entre diferentes componentes de una aplicación. En el contexto de Spring Boot, la inyección de dependencias se refiere a cómo Spring maneja las dependencias de los componentes y proporciona instancias de estas dependencias a los componentes que las necesitan (en nuestro ejemplo la creación de un objeto de la clase ChisteService la realiza autamáticamente Sprint Boot, en ningún lado hacemos un new de la clase ChisteService)

  • Ahora nuevamente en el paquete 'com.example.demo' procedemos a crear la carpeta 'controller' como en el proyecto anterior

    Y en el diálogo procedemos a indicar el nombre 'controller'

    En la carpeta controller procedemos a crear la clase ChisteController.

    El código de la clase ChisteController es diferente al proyecto que no usaba servicios:

    package com.example.demo.controller;
    
    import com.example.demo.model.Chiste;
    import com.example.demo.service.ChisteService;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class ChisteController {
    
        private final ChisteService chisteService;
    
        public ChisteController(ChisteService chisteService) {
            this.chisteService = chisteService;
        }
    
        @GetMapping("/")
        public String inicio(Model model) {
            Chiste chisteAzar = chisteService.obtenerChisteAleatorio();
            model.addAttribute("chiste", chisteAzar);
            return "index";
        }
    }
    

    La anotación @Controller marca esta clase como un controlador de Spring.

        private final ChisteService chisteService;
    
        public ChisteController(ChisteService chisteService) {
            this.chisteService = chisteService;
        }
    

    En esta parte, se define un campo chisteService que representa la dependencia del servicio ChisteService. Este campo se inicializa a través de un constructor que toma una instancia de ChisteService. Esto se llama inyección de dependencias y Spring se encargará de proporcionar una instancia de ChisteService automáticamente al crear una instancia de ChisteController (tener en cuenta que también Spring Boot crea una instancia de ChisteController en forma automática)

    El método inicio maneja las solicitudes GET a la raíz de la aplicación (/). Toma un parámetro Model, que es utilizado para pasar datos a la vista. En este método, se obtiene un chiste aleatorio utilizando el servicio ChisteService, se agrega al modelo con el nombre "chiste" y se devuelve el nombre de la vista "index". Esto indica que Spring debe buscar una plantilla de Thymeleaf llamada index.html para renderizar la respuesta al cliente.

  • Ahora procedamos a crear la vista en la carpeta 'template' el archivo index.html, sin hacer cambios con respecto al proyecto del concepto anterior:

    El código fuente de la página index.html es:

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8">
        <title>Proyecto004</title>
    </head>
    
    <body>
        <h1>Chiste</h1>
        <p th:text="${chiste.texto}"></p>
    </body>
    
    </html>
    
  • Ahora si ejecutamos la aplicación (recordar siempre de guardar todos los archivos modificados y volver a reiniciar el servidor) vemos que nos muestra chistes distintos cada vez que actualizamos la página web:

    pagina web dinámica con Thymeleaf utilizando MVC y Service