En las lecciones anteriores vimos los fundamentos de Spring MVC: la arquitectura, las anotaciones clave y los principios básicos de enrutamiento. Ahora es momento de aplicar ese conocimiento en la práctica y crear una API REST completa.
Vamos a diseñar un controlador para gestionar libros en una biblioteca. Nuestra API podrá obtener la lista de libros, buscar un libro por ID, añadir libros nuevos, actualizar su información y eliminarlos de la base. En el proceso crearemos todas las operaciones CRUD necesarias, aprenderemos a manejar correctamente los métodos HTTP (GET, POST, PUT, DELETE), configuraremos la devolución de datos en formato JSON y añadiremos pruebas básicas.
La API REST es la base del desarrollo web moderno. Ya sea que desarrolles una aplicación web, una app móvil o una arquitectura de microservicios, tendrás que crear y mantener API-endpoints. ¡Aprendamos a hacerlo bien!
1. Preparación del proyecto
Dependencias. Para empezar, asegúrate de que tu proyecto Spring Boot está configurado correctamente. Incluye en el proyecto las dependencias necesarias en el archivo pom.xml:
<dependencies>
<!-- Spring Web para trabajar con MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dependencia para trabajar con JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
Bueno, ahora manos a la obra y creemos el controlador.
2. Descripción de la entidad Book
Antes de implementar el controlador necesitamos la entidad que va a manejar. Creamos una clase sencilla para la entidad Book.
package com.example.demo.model;
public class Book {
private Long id;
private String title;
private String author;
// Constructores
public Book() {}
public Book(Long id, String title, String author) {
this.id = id;
this.title = title;
this.author = author;
}
// Getters y setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
3. Creación del REST-controller
Ahora estamos listos para crear nuestro controlador. Manejará las solicitudes HTTP para gestionar libros. Usaremos la anotación @RestController para indicar a Spring que esta clase atiende solicitudes REST.
package com.example.demo.controller;
import com.example.demo.model.Book;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
private final List<Book> books = new ArrayList<>();
// Inicialización de datos
public BookController() {
books.add(new Book(1L, "Clean Code", "Robert C. Martin"));
books.add(new Book(2L, "Effective Java", "Joshua Bloch"));
}
// Obtener todos los libros
@GetMapping
public List<Book> getAllBooks() {
return books;
}
// Obtener libro por ID
@GetMapping("/{id}")
public Book getBookById(@PathVariable Long id) {
return books.stream()
.filter(book -> book.getId().equals(id))
.findFirst()
.orElseThrow(() -> new RuntimeException("Book not found"));
}
// Crear nuevo libro
@PostMapping
public Book createBook(@RequestBody Book book) {
books.add(book);
return book;
}
// Actualizar libro
@PutMapping("/{id}")
public Book updateBook(@PathVariable Long id, @RequestBody Book updatedBook) {
Book book = getBookById(id);
book.setTitle(updatedBook.getTitle());
book.setAuthor(updatedBook.getAuthor());
return book;
}
// Eliminar libro
@DeleteMapping("/{id}")
public void deleteBook(@PathVariable Long id) {
Book book = getBookById(id);
books.remove(book);
}
}
4. Análisis del código del controlador
Principales métodos del controlador
- GET
/booksDevuelve la lista de todos los libros. Muy sencillo, usa la variablebookspara devolver la lista. - GET
/books/{id}Busca un libro por ID. Si no se encuentra, se lanza una excepción (se puede mejorar el manejo de errores más adelante). - POST
/booksCrea un libro nuevo. Pasamos un objetoBooken el cuerpo de la petición (anotación@RequestBody). - PUT
/books/{id}Actualiza un libro existente por ID. Primero buscamos el libro por ID y luego actualizamos sus datos. - DELETE
/books/{id}Elimina un libro por ID. Primero buscamos el libro y luego lo quitamos de la lista.
Parámetros de las anotaciones
@RequestMapping("/books"): ruta base para todas las solicitudes.@GetMapping,@PostMapping,@PutMapping,@DeleteMapping: manejan los distintos métodos HTTP.@PathVariableextrae parámetros desde la ruta de la petición.@RequestBodylee el cuerpo de la petición y lo convierte en un objeto Java.
5. Pruebas del controlador
Puedes comprobar la API usando herramientas como Postman o curl. Ejemplos de peticiones:
GET todos los libros
GET http://localhost:8080/books
GET libro por ID
GET http://localhost:8080/books
POST nuevo libro
POST http://localhost:8080/books
Content-Type: application/json
{
"id": 3,
"title": "The Pragmatic Programmer",
"author": "Andrew Hunt"
}
DELETE eliminar libro
DELETE http://localhost:8080/books/1
6. Errores típicos y cómo solucionarlos
- Error
404 Not FoundenGET /books/{id}Esto ocurre si el libro buscado no está en la lista. Asegúrate de que la variablebooksesté inicializada correctamente. - Error en la serialización JSON Comprueba que todos los campos de los objetos tengan getters/setters; si no, Jackson no podrá convertir el objeto a JSON.
- Error
415 Unsupported Media Typeen peticionesPOSToPUTAsegúrate de que la cabecera de la petición incluyaContent-Type: application/json.
¡Ahora tenemos un controlador REST completamente funcional! En la siguiente clase conoceremos el motor de plantillas Thymeleaf, para aprender a crear páginas HTML atractivas para nuestras aplicaciones web.
GO TO FULL VERSION