En el concepto anterior desarrollamos una página dinámica que muestra un chiste en forma aleatorio. Vamos a desarrollar el mismo problema pero en vez de retornar una página dinámica en HTML, vamos a retornar un archivo JSON con un chiste al azar y otra URL va a retornar un JSON con todos los chistes.
Las URL para hacer las peticiones serán:
http://localhost:8080/chisteazar http://localhost:8080/chistetodos
Lo primero que vamos a hacer notar que gran parte es lo mismo. Debemos crear el modelo, el servicio y el controlador (veremos que en la clase del controlador es donde tenemos más diferencias, además no dispondremos nada en la carpeta template ya que no retornaremos HTML dinámico, no necesitamos el módulo de ThymeLeap)
Los pasos para crear el proyecto:
Desde el menú de opciones seleccionamos File-> New -> Spring Starter Project:
En el primer diálogo procedemos a definir el nombre de nuestro proyecto. Utilizaremos Maven como herramienta de gestión de proyecto.
En el segundo diálogo seleccionamos solo la dependencia "Spring Web" y no "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', igual que en el ejemplo anterior.
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() { } public Chiste(String texto) { this.texto = texto; } public String getTexto() { return texto; } public void setTexto(String texto) { this.texto = texto; } }
Igual que en el ejercicio anterior, procedemos a presionar con el botón derecho del mouse el paquete 'com.example.demo' y crear la carpeta 'service'
Y en el diálogo procedemos a indicar el nombre 'service' (es una convención comúnmente adoptada)
En la carpeta service procedemos a crear la clase ChisteService igual que en el concepto anterior y agregamos un método que retorne todos los chistes:
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())); } public List<Chiste> todos() { return chistes; } }
Recordemos que 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)
Lo único que hemos hecho diferente al ejercicio anterior, es agregar un método que retorne todos los chistes (podríamos no haberlo hecho):
public List<Chiste> todos() { return chistes; }
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, ya que vamos a retornar archivos JSON en lugar de páginas dinámicas:
package com.example.demo.controller; import java.util.List; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import com.example.demo.model.Chiste; import com.example.demo.service.ChisteService; @RestController public class ChisteController { private final ChisteService chisteService; public ChisteController(ChisteService chisteService) { this.chisteService = chisteService; } @GetMapping("/chisteazar") public Chiste chisteazar() { Chiste chisteAzar = chisteService.obtenerChisteAleatorio(); return chisteAzar; } @GetMapping("/chistetodos") public List <Chiste> chisteTodos() { List<Chiste> chistes=chisteService.todos(); return chistes; } }
Un cambio fundamental es que disponemos la anotación @RestController en lugar de @Controller.
La anotación @RestController se utiliza para crear controladores en Spring Boot que devuelvan datos serializados en JSON por defecto. Sin necesidad de usar una vista para renderizar los datos en la respuesta (no disponemos archivos HTML en la carpeta template). Esto es útil cuando se construyen servicios web RESTful donde la salida principal es el contenido de datos.
Ahora cada una de las URL retornan la estructura de datos en formato JSON (el framework Spring Boot se encarga de la serialización):
@GetMapping("/chisteazar") public Chiste chisteAzar() { Chiste chisteAzar = chisteService.obtenerChisteAleatorio(); return chisteAzar; } @GetMapping("/chistetodos") public List <Chiste> chisteTodos() { List<Chiste> chistes=chisteService.todos(); return chistes; }
El método 'chisteAzar' retorna un objeto de tipo Chiste y el método 'chisteTodos' retorna un objeto de tipo List con elementos de tipo Chiste (no retornamos tipo de dato String como en el ejemplo anterior)
Controlar que hayamos creado los paquetes y archivos respectivos. Recordemos que cada proyecto que desarrollemos tendrá una estructura similar e iremos agregando otras secciones.
Podemos ingresar a las 2 URL y comprobar que al navegador llegan archivos JSON (no retorna HTML)
La ruta: http://localhost:8080/chisteazar:
La segunda ruta retorna todos los chistes (un arreglo con todos los chistes):
Para probar las APIs que desarrollemos, no es cómodo hacer las peticiones desde un navegador, sobretodo cuando tengamos que hacer peticiones POST, PUT, DELETE. Para solventar dicho problema se existen aplicaciones orientadas para probar APis.
Postman es una herramienta popular utilizada por desarrolladores para probar, desarrollar y documentar APIs. Es una aplicación que proporciona una interfaz gráfica de usuario para enviar solicitudes HTTP a servidores web y recibir respuestas. Postman simplifica el proceso de probar APIs al ofrecer una variedad de características útiles, como la organización de solicitudes en colecciones, la capacidad de definir variables de entorno y globales, la automatización de pruebas mediante scripts en JavaScript, la generación de documentación de APIs, entre otras.
Puede descargar la aplicación desde su sitio oficial en forma gratuita:sitio oficial.
Una vez instalado puede proceder a efectuar las solicitudes, teniendo en cuenta que son peticiones GET:
http://localhost:8080/chisteazar
La segunda petición es la que retorna un arreglo:
http://localhost:8080/chistetodos
Tener en cuenta que nos va a ser de suma utilidad para otros métodos de HTTP: