Proyecto
Form Dev
Guía Definitiva
Construcción del Backend
con Spring Boot
José Luis Galvis
Full Stack Dev
Abril 2025
Modelo Arquitectónico
El proyecto sigue una arquitectura por capas adaptada al
patrón MVC para APIs REST, garantizando modularidad,
escalabilidad, y mantenibilidad. Las capas son:
1. Capa de Presentación (Controladores)
Clases: AuthController, HomeController.
Propósito: Maneja solicitudes HTTP desde el frontend
(Angular), delega la lógica a los servicios, y retorna
respuestas JSON.
Tecnologías: Anotaciones @RestController, @PostMapping,
@GetMapping, @RequestMapping.
Criterio: Actúa como la interfaz de la API, aislando las rutas
HTTP.
2. Capa de Servicios (Lógica de Negocio)
Clases: UserService.
Propósito: Implementa la lógica de negocio (validar emails,
encriptar contraseñas, autenticar usuarios) y coordina entre
controladores y repositorios.
Patrones: Transaction Script para operaciones simples.
Criterio: Centraliza la lógica para facilitar pruebas y reducir
acoplamiento.
3. Capa de Persistencia (Acceso a Datos)
Clases: UserRepository.
Propósito: Gestiona operaciones CRUD en la base de datos
MySQL.
Tecnologías: Spring Data JPA con métodos automáticos
(save, findAll) y personalizados (findByEmail).
Criterio: Abstrae el acceso a datos, simplificando
operaciones.
4. Capa de Seguridad
Clases: SecurityConfig.
Propósito: Configura CORS y encripta contraseñas con
BCrypt.
Criterio: Garantiza seguridad y accesibilidad desde el
frontend.
5. Capa de Dominio (Modelo)
Clases: User (entidad), UserDTO, UserResponseDTO,
LoginDTO.
Propósito: Define la estructura de datos (entidad para la
base de datos, DTOs para transferencia) y validaciones.
Criterio: Protege la integridad y seguridad de los datos.
6. Capa de Manejo de Errores
Clases:
GlobalExceptionHandler, EmailAlreadyExistsException,
InvalidPasswordException.
Propósito: Centraliza el manejo de excepciones,
retornando respuestas HTTP consistentes.
Criterio: Mejora la experiencia del usuario y elimina código
repetitivo.
¿Es MVC?
Sí, adaptado a REST:
Modelo: User (datos persistentes),
UserDTO/UserResponseDTO/LoginDTO (intercambio con
frontend).
Vista: JSON consumido por Angular, no HTML.
Controlador: AuthController, HomeController (manejan
rutas y respuestas).
Patrones Clave
DTO: UserDTO, UserResponseDTO, LoginDTO para
transferencia segura.
Inyección de Dependencias: Constructor-based injection en
UserService y AuthController.
Repositorio: UserRepository con Spring Data JPA.
Manejo Centralizado de Errores: GlobalExceptionHandler con
@ControllerAdvice.
SOLID: Responsabilidad única en cada clase.
Orden de Construcción
El Backend se construye en un orden lógico para resolver
dependencias y habilitar funcionalidades incrementalmente:
FormsApplication: Inicia la aplicación.
User: Define la entidad de la base de datos.
UserDTO, UserResponseDTO, LoginDTO: Estructuran datos
de entrada/salida.
UserRepository: Habilita acceso a datos.
SecurityConfig: Configura seguridad y CORS.
UserService: Implementa lógica de negocio.
EmailAlreadyExistsException, InvalidPasswordException:
Definen excepciones personalizadas.
GlobalExceptionHandler: Maneja errores.
AuthController: Expone endpoints REST.
HomeController: Agrega una ruta de prueba.
SwaggerConfig: Documenta la API.
UserServiceTest: Valida la lógica con pruebas unitarias.
Detalle de Cada Clase
1. FormsApplication
Propósito: Punto de entrada que inicia Spring Boot.
Cómo se construye:
Anotación @SpringBootApplication: Habilita configuración
automática, escaneo de componentes, y definición de
beans.
Método main: Lanza el servidor embebido (Tomcat).
Por qué primero: Establece el contexto de Spring Boot.
2. User
Propósito: Entidad JPA que mapea la tabla users en MySQL.
Cómo se construye:
Anotaciones: @Entity, @Table, @Id, @GeneratedValue,
@Column, @Email, @NotNull, @PrePersist.
Atributos: id, firstName, lastName, email (único), password,
createdAt.
Usa Lombok (@Getter, @Setter, @ToString(exclude =
"password")) para reducir boilerplate.
Por qué segundo: Define la estructura de datos principal.
3. UserDTO, UserResponseDTO, LoginDTO
Propósito: DTOs para transferencia de datos, evitando
exponer la entidad User.
Cómo se construye:
UserDTO: Entrada para registro con validaciones (@NotBlank,
@Email, @Size, @Pattern).
UserResponseDTO: Salida segura, omitiendo password.
LoginDTO: Entrada para login con validaciones.
Usa Lombok (@Getter, @Setter).
Por qué tercero: Define los contratos de datos para el
frontend.
4. UserRepository
Propósito: Interfaz para operaciones CRUD en la tabla users.
Cómo se construye:
Extiende JpaRepository<User, Long> para métodos
automáticos.
Método personalizado: Optional<User> findByEmail(String
email).
Por qué cuarto: Proporciona acceso a datos para
UserService.
5. SecurityConfig
Propósito: Configura seguridad (BCrypt, CORS) y políticas de
acceso.
Cómo se construye:
Anotaciones: @Configuration, @EnableWebSecurity.
Beans: PasswordEncoder, CorsConfigurationSource,
SecurityFilterChain.
Permite todas las rutas (puedes restringir /api/users a
ADMIN en el futuro).
Por qué quinto: Asegura la API antes de exponer endpoints.
6. UserService
Propósito: Implementa lógica de negocio (registro, login,
listar usuarios).
Cómo se construye:
Anotación: @Service.
Inyección por constructor: UserRepository,
PasswordEncoder.
Métodos: registerUser, loginUser, getAllUsers.
Valida email único y contraseña no vacía.
Por qué sexto: Depende de UserRepository y SecurityConfig.
[Link],
InvalidPasswordException
Propósito: Excepciones personalizadas para email duplicado
y contraseña inválida.
Cómo se construye:
Extienden RuntimeException.
Incluyen un constructor con mensaje.
Por qué séptimo: Necesarias para validaciones en
UserService.
8. GlobalExceptionHandler
Propósito: Centraliza el manejo de excepciones con
respuestas HTTP.
Cómo se construye:
Anotación: @ControllerAdvice.
Maneja RuntimeException con código 400.
Por qué octavo: Captura errores de UserService y
controladores.
9. AuthController
Propósito: Expone endpoints REST para registro, login, y
consulta de usuarios.
Cómo se construye:
Anotaciones: @RestController, @RequestMapping("/api"),
@Tag, @Operation.
Inyección por constructor: UserService.
Endpoints: /register (201 Created), /login, /users.
Usa @Valid para validaciones y UserResponseDTO para
respuestas seguras.
Por qué noveno: Depende de UserService y SecurityConfig.
10. HomeController
Propósito: Ruta de prueba en /.
Cómo se construye:
Anotación: @RestController.
Retorna JSON con un mensaje de bienvenida.
Por qué décimo: Opcional, creado al final.
11. SwaggerConfig
Propósito: Documenta la API con Swagger.
Cómo se construye:
Anotación: @Configuration.
Bean: OpenAPI con título, versión, descripción, y contacto.
Por qué undécimo: Agregado para documentación.
12. UserServiceTest
Propósito: Pruebas unitarias para UserService.
Cómo se construye:
Usa JUnit 5 y Mockito
(@ExtendWith([Link])).
Cubre casos: registro exitoso, email duplicado, contraseña
vacía, login exitoso, login fallido (email no encontrado,
contraseña incorrecta), y consulta de usuarios.
Por qué duodécimo: Valida la lógica después de
implementar servicios.
Resumen
Este Backend implementa un sistema de registro y login
con:
Arquitectura: Capas claras (presentación, servicios,
persistencia, seguridad, dominio, errores).
Patrones: DTO, inyección de dependencias, repositorio,
manejo centralizado de errores, SOLID.
Características:
Registro y login con validaciones robustas.
Encriptación de contraseñas con BCrypt.
Documentación con Swagger
([Link]
Pruebas unitarias completas con JUnit y Mockito.
Fortalezas del Proyecto:
Código limpio con Lombok y inyección por constructor.
Validaciones en DTOs (@NotBlank, @Email, @Pattern).
Excepciones personalizadas y manejo centralizado.
Cobertura de pruebas para casos felices y de error.
Este proyecto es un punto de partida ideal para aprender:
Desarrollo de APIs REST con Spring Boot.
Persistencia con JPA y MySQL.
Seguridad con BCrypt y CORS.
Pruebas unitarias con JUnit y Mockito.
José Luis Galvis
Full Stack Dev