🧱 Arquitectura del Sistema – MiniTweet API
MiniTweet API está desarrollada con una arquitectura n-tier (multicapa) basada en buenas prácticas de diseño con Spring Boot. Esta estructura favorece la separación de responsabilidades, la escalabilidad y el mantenimiento limpio del código.
MiniTweet API está desarrollada con una arquitectura n-tier (multicapa) basada en buenas prácticas de diseño con Spring Boot. Esta estructura favorece la separación de responsabilidades, la escalabilidad y el mantenimiento limpio del código. Además, se hace uso de Programación Orientada a Objetos (POO) para modelar entidades y comportamientos del dominio de forma clara y reutilizable.
🗂️ Capas principales
MiniTweet se organiza en cuatro capas principales, cada una con una responsabilidad específica:
1️⃣ Capa de Controladores (controllers/
)
- 📍 Responsabilidad: Maneja las solicitudes HTTP entrantes.
- 💬 Interactúa directamente con el usuario o cliente (frontend o app móvil).
- 🧠 Delegan la lógica a los servicios.
- 🚫 No contiene lógica de negocio.
@PostMapping("/register")
public ResponseEntity<GeneralResponse>registerUser(@RequestBody @Valid RegisterUserDto userDto){
try{
userService.registerUser(userDto);
return GeneralResponse.getResponse(HttpStatus.CREATED, "User registered successfully");
}catch (HttpError e){
return GeneralResponse.getResponse(e.getHttpStatus(), e.getMessage());
}
}
2️⃣ Capa de Servicios (services/
)
- 🛠️ Responsabilidad: Contiene la lógica de negocio.
- 🔄 Interactúa con los repositorios para acceder a la base de datos.
- 📦 Agrupa funcionalidades relacionadas (usuarios, publicaciones, comentarios).
- 🔐 Puede aplicar reglas de validación o seguridad.
@Override
@Transactional(rollbackOn = Exception.class)
public Boolean isTokenValid(User user, String token) {
try {
cleanToken(user);
List<Token> tokens = tokenRepository.findByUserAndActive(user, true);
tokens.stream()
.map(t -> t.getContent().equals(token))
.findAny()
.orElseThrow(() -> new HttpError(HttpStatus.UNAUTHORIZED, "Token not valid"));
return true;
} catch (HttpError e) {
throw e;
}
}
3️⃣ Capa de Repositorios (repositories/
)
- 🗄️ Responsabilidad: Interactúa directamente con la base de datos.
- 🔍 Utiliza Spring Data JPA para realizar consultas.
- 📑 Peticiones con Hibernate Query Language (HQL).
- 💾 Realiza operaciones CRUD sobre las entidades.
@Repository
public interface CommentRepository extends JpaRepository<Comment, UUID> {
List<Comment>findAllByPost(Post post);
Comment findByIdAndAuthor(UUID id, User authorId);
}
4️⃣ Capa de Entidades (domain/
)
- 🏷️ Responsabilidad: Define las entidades del dominio.
- 🧩 Modela los objetos del negocio (usuarios, publicaciones, comentarios).
- 🔗 Utiliza anotaciones JPA para mapear a la base de datos.
@Data
@Entity
@Table(name = "roles")
public class Role {
@Id
private String id;
@Column(nullable = false, unique = true, columnDefinition = "VARCHAR(50)")
private String name;
@ManyToMany(mappedBy = "roles")
@JsonIgnore
private List<User> users;
}
🛠️ Otras capas y componentes importantes
🧾 DTOs (Data Transfer Objects)
- 📦 Utilizados para transferir datos entre capas.
- 📝 Definen la estructura de los datos que se envían o reciben.
- 🚫 No contienen lógica de negocio.
🔒 Seguridad y Autenticación (Spring Security y JWT)
- 🔐 Validacion de roles y permisos.
- 🛡️ Protege los endpoints con roles y permisos.
- 📜 Configura filtros de seguridad para validar tokens.
- 🗝️ Utiliza un
UserDetailsService
para cargar usuarios desde la base de datos. - 🔑 Genera y valida tokens JWT para acceso seguro.
☁️ Integración con Cloudinary
- 🌥️ Maneja la carga y gestión de imágenes.
- 📸 Utiliza la API de Cloudinary para almacenar imágenes.
- 🔗 Configuración en
application.properties
para acceder a las credenciales de Cloudinary
🛠️ Manejador Global de Errores
- 📦 Utiliza un
@ControllerAdvice
para manejar excepciones de forma centralizada. - 🔍 Captura excepciones específicas y devuelve respuestas adecuadas.
- 🛡️ Protege la aplicación de filtraciones de información sensible.
@RestControllerAdvice
public class GlobalErrorHandler {
@ExceptionHandler(HttpError.class)
public ResponseEntity<GeneralResponse> handleHttpError(HttpError e) {
return GeneralResponse.getResponse(e.getHttpStatus(), e.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<GeneralResponse> handleGenericError(Exception e) {
return GeneralResponse.getResponse(HttpStatus.INTERNAL_SERVER_ERROR, "Internal Server Error");
}
}
🛠️ Excepción Personalizada HttpError
- 📦 Extiende de
RuntimeException
. - 🔍 Permite manejar errores HTTP de forma consistente.
- 🛡️ Incluye información sobre el estado y el mensaje del error.
- 📜 Facilita la creación de respuestas de error personalizadas.
@Getter
public class HttpError extends RuntimeException {
private final HttpStatus httpStatus;
public HttpError(HttpStatus httpStatus, String message){
super(message);
this.httpStatus = httpStatus;
}
}
🧩 Resumen de la Arquitectura
MiniTweet API sigue una arquitectura limpia y modular, donde cada capa tiene una responsabilidad clara. Esto permite un desarrollo ágil, pruebas unitarias efectivas y una fácil escalabilidad. La separación de preocupaciones facilita el mantenimiento y la evolución del sistema a lo largo del tiempo. Esta estructura modular también permite que diferentes equipos trabajen en paralelo en distintas capas sin interferencias, lo que mejora la productividad y la calidad del código.
🔄 Flujo de una petición
[Cliente (Postman / App / Frontend)]
↓
[Controller] → [Service] → [Repository] → [Base de datos]
↓
[Response al Cliente]
🛡️ Las respuestas siguen este camino en sentido inverso.
✨ Ventajas de esta arquitectura
- 🔍 Claridad: Cada capa tiene una única responsabilidad.
- ♻️ Reutilización: Lógica de negocio centralizada y reutilizable.
- 🔒 Seguridad: Filtros y capas de autenticación aisladas.
- 🚀 Escalabilidad: Puedes agregar nuevas funcionalidades sin afectar otras capas.
- 🧪 Testabilidad: Fácil de probar cada capa de forma independiente.
📌 Para más detalles sobre la implementación y el uso de MiniTweet API, consulta la sección Guía de Inicio Rápido.
📚 ¿ Te interesa la seguridad del sistema? Consulta la sección Autenticación.