Tổng quan kiến trúc hệ thống

Nội dung chi tiết

1. Tổng quan kiến trúc hệ thống

1.1. Mục tiêu kiến trúc

Kiến trúc backend được thiết kế nhằm:

Tất cả các service backend phải tuân thủ kiến trúc chuẩn được định nghĩa trong tài liệu này.


1.2. Mô hình kiến trúc

Hệ thống backend sử dụng mô hình:

Modular Monolith – Layered Architecture

Đặc điểm:

Sơ đồ tổng thể:

image.png

Tích hợp ngoài:

image.png


1.3. Quy tắc phân lớp (Layered Architecture)

Mỗi module phải tuân thủ cấu trúc phân lớp sau:

controller service repository entity dto mapper exception

1.3.1. Controller Layer (API Layer)

Chức năng:

Quy định:

Ví dụ:


@RestController @RequestMapping("/api/users") public class UserController { private final UserService userService; @PostMapping public ApiResponse<UserResponse> create(@Valid @RequestBody UserRequest req) { return ApiResponse.success(userService.create(req)); } }

1.3.2. Service Layer (Business Layer)

Chức năng:

Quy định:

Ví dụ:


@Service public class UserService { @Transactional public UserResponse create(UserRequest req) { User entity = mapper.toEntity(req); repository.save(entity); return mapper.toResponse(entity); } }

1.3.3. Repository Layer (Persistence Layer)

Chức năng:

Quy định:

Ví dụ:


public interface UserRepository extends JpaRepository<User, Long> { }

1.3.4. Entity Layer

Chức năng:

Quy định:


1.3.5. DTO Layer

Gồm:

Chức năng:

Quy định:


1.3.6. Mapper Layer

Chức năng:

Có thể dùng:

Quy định:


1.4. Quy tắc phụ thuộc (Dependency Direction)

Dependency chỉ được phép đi theo một chiều:


Controller → Service → Repository → DB

Không được phép:

Nguyên tắc:

Layer trên được gọi layer dưới
Layer dưới không được gọi layer trên


1.5. Tổ chức module theo domain

Project được tổ chức theo domain thay vì technical layer toàn cục.

Cấu trúc chuẩn:


com.company.project ├── common │ ├── config │ ├── exception │ ├── util │ ├── user │ ├── controller │ ├── service │ ├── repository │ ├── entity │ ├── dto │ ├── mapper │ ├── document │ ├── controller │ ├── service │ ├── repository │ ├── entity │ ├── dto │ ├── mapper

1.6. Tích hợp hệ thống ngoài

Backend có thể tích hợp các thành phần sau:

Quy tắc tích hợp:

Ví dụ:


integration ├── sso │ ├── SsoClient │ ├── redis │ ├── RedisService │ ├── external │ ├── ExternalApiClient

1.7. Nguyên tắc kiến trúc bắt buộc

Tất cả backend service phải tuân thủ:

Vi phạm kiến trúc được xem là lỗi nghiêm trọng trong review code.


1.8. Khả năng mở rộng Microservice

Kiến trúc hiện tại cho phép tách module thành microservice khi cần:

Ví dụ:


user module → user-service document moduledocument-service auth module → auth-service

1.9. Xử lý ngoại lệ toàn cục (Exception Handling Strategy)

1.9.1. Mục tiêu

Chuẩn hóa cơ chế xử lý lỗi toàn hệ thống nhằm:

Tất cả API backend phải sử dụng cơ chế xử lý ngoại lệ toàn cục.


1.9.2. Global Exception Handler

Hệ thống sử dụng Global Exception Handler thông qua @ControllerAdvice.

Chức năng:

Quy định:

Ví dụ:


@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity<ApiError> handleNotFound(ResourceNotFoundException ex) { return build(HttpStatus.NOT_FOUND, ex.getCode(), ex.getMessage()); } @ExceptionHandler(AccessDeniedException.class) public ResponseEntity<ApiError> handleForbidden(AccessDeniedException ex) { return build(HttpStatus.FORBIDDEN, "ACCESS_DENIED", "Access denied"); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<ApiError> handleValidation(MethodArgumentNotValidException ex) { return build(HttpStatus.BAD_REQUEST, "VALIDATION_ERROR", "Invalid request"); } @ExceptionHandler(Exception.class) public ResponseEntity<ApiError> handleSystem(Exception ex) { return build(HttpStatus.INTERNAL_SERVER_ERROR, "SYSTEM_ERROR", "Internal server error"); } private ResponseEntity<ApiError> build(HttpStatus status, String code, String message) { ApiError error = ApiError.of(code, message); return ResponseEntity.status(status).body(error); } }

1.9.3. Mapping Exception → HTTP Status

Chuẩn mapping bắt buộc:

Exception HTTP Status
ValidationException 400 Bad Request
MethodArgumentNotValid 400 Bad Request
IllegalArgumentException 400 Bad Request
AccessDeniedException 403 Forbidden
AuthenticationException 401 Unauthorized
ResourceNotFoundException 404 Not Found
BusinessException 422 Unprocessable
SystemException 500 Internal Server Error
Exception (default) 500 Internal Server Error

Không được trả:


1.9.4. Chuẩn format response lỗi

Tất cả API khi lỗi phải trả format thống nhất:


{ "timestamp": "2026-02-23T10:15:30Z", "code": "USER_NOT_FOUND", "message": "User not found", "traceId": "abc123" }

Ý nghĩa:

Field Mô tả
timestamp Thời điểm lỗi
code Mã lỗi hệ thống
message Thông báo lỗi
traceId ID truy vết log

Quy định:


1.9.5. Quy tắc định nghĩa Exception

Mỗi loại lỗi phải có class riêng:


exception ├── ResourceNotFoundException ├── ValidationException ├── BusinessException ├── SystemException

Ví dụ:


public class ResourceNotFoundException extends RuntimeException { private final String code; public ResourceNotFoundException(String code, String message) { super(message); this.code = code; } public String getCode() { return code; } }

1.9.6. Quy tắc sử dụng Exception

Service layer phải throw exception domain:


public User getUser(Long id) { return repository.findById(id) .orElseThrow(() -> new ResourceNotFoundException( "USER_NOT_FOUND", "User not found" )); }

Không được:


1.9.7. TraceId và logging

Mỗi request phải có traceId để truy vết lỗi:

Ví dụ:


public class ApiError { private String timestamp; private String code; private String message; private String traceId; public static ApiError of(String code, String message) { ApiError e = new ApiError(); e.timestamp = Instant.now().toString(); e.code = code; e.message = message; e.traceId = MDC.get("traceId"); return e; } }

1.9.8. Nguyên tắc bắt buộc

Tất cả backend service phải tuân thủ:

Vi phạm quy tắc xử lý lỗi được xem là lỗi nghiêm trọng trong code review