Curso de Spring Boot
Cuando una API crece y la usan muchos clientes (frontend, apps móviles, otros servicios), es importante diseñarla de forma profesional.
Las APIs modernas deben tener:
- versionado
- respuestas consistentes
- paginación
- filtrado
- manejo de errores
- documentación clara
22.1 Versionado de API
Cuando una API cambia, no podemos romper a los clientes existentes.
Por eso se versiona.
Ejemplo:
1/api/v1/users 2/api/v2/users
Ejemplo Controller
1@RestController 2@RequestMapping("/api/v1/users") 3public class UserController { 4 5 @GetMapping 6 public List<UserDTO> getUsers() { 7 return service.getUsers(); 8 } 9 10}
Si cambiamos la API:
1@RequestMapping("/api/v2/users")
22.2 Respuestas estándar de API
En APIs grandes se usa un formato común de respuesta.
Ejemplo:
1{ 2 "success": true, 3 "data": {...}, 4 "message": "User created" 5}
Clase de respuesta
1public class ApiResponse<T> { 2 3 private boolean success; 4 private String message; 5 private T data; 6 7}
Ejemplo uso
1@PostMapping 2public ApiResponse<UserDTO> createUser(@RequestBody CreateUserDTO dto) { 3 4 UserDTO user = service.createUser(dto); 5 6 return new ApiResponse<>(true,"User created", user); 7 8}
22.3 Manejo profesional de errores
Error típico:
1{ 2 "timestamp": "...", 3 "status": 500, 4 "error": "Internal Server Error" 5}
Esto no es muy útil.
Mejor:
1{ 2 "success": false, 3 "error": "USER_NOT_FOUND", 4 "message": "User not found" 5}
Clase ErrorResponse
1public class ErrorResponse { 2 3 private String error; 4 private String message; 5 6}
GlobalExceptionHandler
1@RestControllerAdvice 2public class GlobalExceptionHandler { 3 4 @ExceptionHandler(UserNotFoundException.class) 5 public ResponseEntity<ErrorResponse> handle(UserNotFoundException ex) { 6 7 ErrorResponse error = new ErrorResponse( 8 "USER_NOT_FOUND", 9 ex.getMessage() 10 ); 11 12 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); 13 14 } 15 16}
22.4 Paginación
Nunca devolver miles de registros.
Spring Data tiene paginación integrada.
Repository
1public interface UserRepository extends JpaRepository<User,Long> { 2 3}
Controller
1@GetMapping 2public Page<User> getUsers(Pageable pageable) { 3 4 return repository.findAll(pageable); 5 6}
Petición
1/users?page=0&size=10
22.5 Ordenación
Podemos ordenar resultados.
Ejemplo:
1/users?sort=name
Orden descendente:
1/users?sort=name,desc
22.6 Filtros simples
Podemos filtrar datos.
Ejemplo:
1/users?email=test@email.com
Repository
1List<User> findByEmail(String email);
22.7 Filtros dinámicos
Para filtros complejos se usan Specifications.
Ejemplo
1Specification<User> spec = (root, query, cb) -> 2 cb.equal(root.get("email"), email);
Esto permite construir consultas dinámicamente.
22.8 Documentación con Swagger
Swagger permite documentar la API automáticamente.
Acceso:
1http://localhost:8080/swagger-ui.html
Ejemplo anotación
1@Operation(summary = "Obtener todos los usuarios") 2@GetMapping 3public List<UserDTO> getUsers() { 4 5}
22.9 Buen diseño de endpoints
Incorrecto:
1/getAllUsers 2/createUser 3/deleteUser
Correcto:
1GET /users 2POST /users 3GET /users/{id} 4DELETE /users/{id}
22.10 Códigos HTTP correctos
| Código | Significado |
|---|---|
| 200 | OK |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 404 | Not Found |
| 500 | Server Error |
22.11 Ejemplo completo de API profesional
Controller:
1@GetMapping("/{id}") 2public ResponseEntity<ApiResponse<UserDTO>> getUser(@PathVariable Long id) { 3 4 UserDTO user = service.getUser(id); 5 6 return ResponseEntity.ok( 7 new ApiResponse<>(true,"User found",user) 8 ); 9 10}
Respuesta:
1{ 2 "success": true, 3 "message": "User found", 4 "data": { 5 "id": 1, 6 "name": "Ana" 7 } 8}
22.12 Buenas prácticas
Usar nombres REST claros
/users
/courses
/orders
Usar DTO
Nunca devolver entidades directamente.
Manejar errores correctamente
Centralizar con @RestControllerAdvice.
Documentar APIs
Usar Swagger.
- Loading...