Tài liệu hướng dẫn quy trình phát triển Api sử dụng Springboot
- Tổng quan kiến trúc hệ thống
- Chương 1: Setup môi trường
- Chương 2: Hướng dẫn phát triển (Developer)
- Luồng xử lý API Backend (API Processing Flow)
- 1.Cấu trúc dự án
- 2.Quy chuẩn phát triển module
- 3.Coding convention
- 4. Quy định thay đổi cấu trúc dữ liệu (Entity & Database)
- 5.Quy định về Database, Schema và Migration
- 6.Audit Log & System Metadata
- 7.API Design & Response Standard
- 8. Cơ chế xác thực & tích hợp SSO (WSO2)
- 9.Git Workflow & Pull Request
- 10.Checklist kiểm tra trước khi merge
- 11.Quy trình phối hợp & quản lý thay đổi liên nhóm
- 12. Connect Database & mẫu CRUD & switch Oracle/MSSQL
- 13.Swagger API Documentation & JWT Testing
- Chương 3: Triển khai hệ thống (Deploy)
- Chương 4: Kiểm thử đơn vị (Unit Test)
- Chương 5: Đóng gói & phát hành (Packaging)
- Chương 6: Sử dụng AI agent skill
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:
-
Đảm bảo khả năng mở rộng và bảo trì lâu dài
-
Tách biệt rõ trách nhiệm giữa các layer
-
Chuẩn hóa cách tổ chức code giữa các module
-
Hỗ trợ phát triển song song nhiều developer
-
Dễ dàng tích hợp các hệ thống ngoài (SSO, Cache, MQ…)
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:
-
Một service Spring Boot deploy độc lập
-
Bên trong chia module theo domain
-
Mỗi module có đầy đủ layer Controller → Service → Repository
-
Có thể tách thành microservice khi cần
Sơ đồ tổng thể:
Tích hợp ngoài:
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:
1.3.1. Controller Layer (API Layer)
Chức năng:
-
Nhận request HTTP
-
Validate input DTO
-
Gọi service xử lý
-
Trả response chuẩn
Quy định:
-
Không chứa business logic
-
Không truy cập DB trực tiếp
-
Không xử lý transaction
-
Không map entity
Ví dụ:
1.3.2. Service Layer (Business Layer)
Chức năng:
-
Chứa toàn bộ business logic
-
Điều phối repository
-
Xử lý transaction
-
Mapping entity ↔ DTO
Quy định:
-
Không nhận HttpServletRequest
-
Không trả Entity ra ngoài
-
Phải qua DTO/Response
-
Transaction đặt tại Service
Ví dụ:
1.3.3. Repository Layer (Persistence Layer)
Chức năng:
-
Truy cập DB
-
Query dữ liệu
-
Mapping ORM
Quy định:
-
Không chứa business logic
-
Không gọi service
-
Chỉ thao tác entity
Ví dụ:
1.3.4. Entity Layer
Chức năng:
-
Mapping bảng DB
-
Quan hệ ORM
Quy định:
-
Không chứa logic nghiệp vụ
-
Không trả trực tiếp ra API
-
Không dùng cho request/response
1.3.5. DTO Layer
Gồm:
-
Request DTO
-
Response DTO
Chức năng:
-
Trao đổi dữ liệu với client
-
Tách biệt entity và API
Quy định:
-
Controller chỉ nhận/trả DTO
-
Không expose entity
1.3.6. Mapper Layer
Chức năng:
-
Chuyển đổi DTO ↔ Entity
Có thể dùng:
-
MapStruct
-
Manual mapping
Quy định:
-
Không đặt trong controller
-
Không đặt trong repository
1.4. Quy tắc phụ thuộc (Dependency Direction)
Dependency chỉ được phép đi theo một chiều:
Không được phép:
-
Repository gọi Service
-
Service gọi Controller
-
Controller gọi Repository trực tiếp
-
DTO gọi Repository
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:
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:
-
SSO / Identity Server
-
Cache (Redis)
-
Message Queue
-
File Storage
-
External API
Quy tắc tích hợp:
-
Gọi qua Service
-
Không gọi trực tiếp từ Controller
-
Tách client class riêng
Ví dụ:
1.7. Nguyên tắc kiến trúc bắt buộc
Tất cả backend service phải tuân thủ:
-
Không expose entity ra API
-
Không viết business logic trong controller
-
Không truy cập DB ngoài repository
-
Không phụ thuộc ngược layer
-
Transaction đặt tại service
-
Mapping qua DTO
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ụ:
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:
-
Đảm bảo response lỗi thống nhất giữa các API
-
Ẩn thông tin nội bộ hệ thống
-
Dễ dàng log và truy vết lỗi
-
Hỗ trợ frontend xử lý lỗi chính xác
-
Tránh trả lỗi không kiểm soát (stacktrace, SQL…)
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:
-
Bắt tất cả exception phát sinh từ Controller / Service
-
Mapping exception → HTTP status
-
Trả response lỗi chuẩn
-
Ghi log lỗi hệ thống
Quy định:
-
Không xử lý lỗi trực tiếp trong Controller
-
Không trả stacktrace ra client
-
Không trả message DB/SQL
-
Không throw Exception chung chung
Ví dụ:
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ả:
-
200 với lỗi business
-
500 với lỗi validation
-
500 với not found
1.9.4. Chuẩn format response lỗi
Tất cả API khi lỗi phải trả format thống nhất:
Ý 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:
-
codephải ổn định, dùng cho frontend -
messagecó thể hiển thị user -
Không trả stacktrace
-
Không trả SQL/exception message nội bộ
1.9.5. Quy tắc định nghĩa Exception
Mỗi loại lỗi phải có class riêng:
Ví dụ:
1.9.6. Quy tắc sử dụng Exception
Service layer phải throw exception domain:
Không được:
-
throw new Exception()
-
throw RuntimeException chung chung
-
trả null thay vì lỗi
-
trả Optional ra controller
1.9.7. TraceId và logging
Mỗi request phải có traceId để truy vết lỗi:
-
Sinh tại filter/interceptor
-
Ghi vào MDC log
-
Trả về response lỗi
Ví dụ:
1.9.8. Nguyên tắc bắt buộc
Tất cả backend service phải tuân thủ:
-
Mọi lỗi phải qua GlobalExceptionHandler
-
Không trả exception raw ra client
-
Không xử lý lỗi trong controller
-
Exception phải có code
-
Response lỗi phải đúng format chuẩn
-
Mapping đúng HTTP status
Vi phạm quy tắc xử lý lỗi được xem là lỗi nghiêm trọng trong code review
Chương 1: Setup môi trường
Chương này hướng dẫn chuẩn bị môi trường phát triển cho dự án, bao gồm cài đặt công cụ cần thiết, cấu hình biến môi trường, thiết lập IDE và kiểm tra kết nối đến các dịch vụ phụ trợ (DB, cache, message broker…). Sau khi hoàn thành, lập trình viên có thể chạy dự án ở môi trường local.
Hướng dẫn setup môi trường và start project
1. Mục tiêu
Hướng dẫn developer:
-
Cài đặt môi trường chạy project
-
Cấu hình biến môi trường
-
Khởi động project Spring Boot
-
Kiểm tra project chạy thành công
2. Yêu cầu hệ thống
2.1. Phần mềm cần cài đặt
| Công cụ | Phiên bản khuyến nghị |
|---|---|
| Java JDK | 17 (bắt buộc) |
| Maven | 3.8+ |
| Git | Mới nhất |
| IDE | IntelliJ IDEA 2023+ |
| PostgreSQL | 14 hoặc 15 |
| DB Tool | DBeaver / PgAdmin |
2.2. Kiểm tra cài đặt
Mở terminal:
Kết quả mong muốn:
Kiểm tra Maven:
3. Clone source code
4. Cấu hình biến môi trường
Project sử dụng file:
4.1. Các biến môi trường cơ bản
Ví dụ file:
#spring.application.name=demo
#server.port=8080
#
## ===== Oracle datasource =====
#spring.datasource.url=jdbc:oracle:thin:@//192.168.0.111:1111/ORCLPDB1
#spring.datasource.username=test
#spring.datasource.password=test
#spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
#
## ===== JPA =====
#spring.jpa.hibernate.ddl-auto=none
#spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.format_sql=true
#spring.jpa.database-platform=org.hibernate.dialect.OracleDialect
#
## ===== Hikari pool (optional) =====
#spring.datasource.hikari.maximum-pool-size=10
#spring.datasource.hikari.minimum-idle=2
#spring.datasource.hikari.connection-timeout=30000
#
#management.endpoints.web.exposure.include=health,info
4.2. Cách chỉnh sửa biến môi trường
Cách 1: Sửa trực tiếp trong file application.properties
Ví dụ đổi DB:
Cách 2: Dùng biến môi trường hệ điều hành
Ví dụ trong application.properties:
Trên Windows (PowerShell)
Trên Linux/Mac
5. Chọn profile chạy
Spring Boot thường dùng profile:
Ví dụ chạy với profile dev.
Cách cấu hình profile
Cách 1: Trong biến môi trường
Windows:
Linux/Mac:
Cách 2: Trong IDE
VM options:
6. Build project
Trong thư mục project:
Nếu build thành công sẽ thấy:
7. Start project
Chạy trong IDE
Trong IntelliJ:
-
Mở project
-
Mở file:
-
Nhấn nút Run
8. Kiểm tra project chạy thành công
Sau khi start, kiểm tra log:
Mở trình duyệt:
Hoặc gọi API:
Chương 2: Hướng dẫn phát triển (Developer)
Chương này mô tả cấu trúc source code, quy ước coding, cách tạo module mới, cách viết API/UI, quy trình commit/branch, và cách chạy/debug dự án trong quá trình phát triển. Mục tiêu giúp developer hiểu kiến trúc và đóng góp code đúng chuẩn.
Luồng xử lý API Backend (API Processing Flow)
1.1. Mục tiêu chương.
Mô tả luồng xử lý chuẩn của một API backend từ khi nhận request đến khi deploy production nhằm:
Thống nhất cách xây dựng API giữa các team
Đảm bảo tuân thủ đầy đủ các quy định kiến trúc
Dễ trace lỗi và audit
Liên kết các chuẩn đã quy định ở các chương trước
1.2. Phạm vi áp dụng:
Áp dụng cho:
Tất cả REST API trong modules/**
Core Team và Partner Team
Tất cả service Spring Boot
1.3. Tổng quan luồng xử lý API
Luồng chuẩn:
1.4. Các bước xử lý chi tiết
Bước 1. Client gọi API
Ví dụ:
POST /api/v1/users
Payload:
{
"username": "test",
"password": "123456"
}
Quy định liên quan:
👉 Chương 7 — API Design & Response Standard
Bước 2. Security / Authentication
Hệ thống kiểm tra:
JWT / SSO token
Permission
Role
Nếu fail:
👉 Chương 8 — Cơ chế xác thực & SSO (WSO2)
Bước 3. Controller nhận request
@PostMapping
public ApiResponse<UserResponse> create(
@Valid @RequestBody UserCreateRequest request) {
return ApiResponse.ok(userService.create(request));
}
Quy định:
Name Controller
Không chứa business logic
👉 Chương 3 — Coding Convention
👉 Chương 7 — API Design
Bước 4. DTO Validation
DTO:
public class UserCreateRequest {
@NotBlank
@Size(max = 100)
private String username;
@NotBlank
private String password;
}
Spring tự validate trước khi vào service.
Nếu lỗi:
400 Bad Request
Response chuẩn:
{
"code": "VALIDATION_ERROR",
"message": "username is required"
}
Quy định:
👉 Chương 3 — Coding Convention (Validation)
👉 Chương 7 — Response Standard
Bước 5. Service xử lý logic
public UserResponse create(UserCreateRequest req) {
log.info("Create user {}", req.getUsername());
UserEntity e = mapper.toEntity(req);
repo.save(e);
return mapper.toResponse(e);
}
Cấu trúc chuẩn 1 hàm service:
Quy định:
👉 Chương 3 — Coding Convention
👉 Chương 4 — Entity & Database
Bước 6. Repiository & Database
userRepository.save(entity);
Nếu thay đổi schema:
update entity
migration script
Quy định:
👉 Chương 4 — Thay đổi Entity & DB
👉 Chương 5 — Schema & Migration
Bước 7. Mapping Response
return UserResponse.builder()
.id(e.getId())
.username(e.getUsername())
.build();
Response chuẩn:
{
"code": "SUCCESS",
"data": {
"id": 1,
"username": "test"
}
}
Quy định:
👉 Chương 7 — Response Standard
Bước 8. Logging & Audit
Trong service:
log.info("User created id={}", e.getId());
Nếu nghiệp vụ quan trọng:
ghi audit_log
Quy định:
👉 Chương 3 — Logging
👉 Chương 6 — Audit Log
Bước 9. Exception Handling
Ví dụ:
if (exists) {
throw new BusinessException("USER_EXISTS");
}
Global handler:
@ExceptionHandler(BusinessException.class)
Response:
{
"code": "USER_EXISTS",
"message": "User already exists"
}
Quy định:
👉 Chương 7 — Response & Error
1.5. Luồng phát triển & release API
Sau khi code xong:
Dev → Commit → PR → Review → Merge → CI Build → Deploy
Bước 10. Commit & PR
Quy định:
👉 Chương 9 — Git Workflow & Pull Request
Bước 11. Checklist trước merge
Quy định:
👉 Chương 10 — Checklist merge
Bước 12. Deploy & Update DB
Nếu có migration:
chạy script
deploy service
Quy định:
👉 Chương 5 — Migration
👉 Chương 12 — Connect DB
1.6. Sơ đồ tổng thể API lifecycle
https://docs.lifetex.vn/link/333#bkmrk-request-%E2%86%93-auth-%28ch8%29
Request
↓
Auth (Ch8)
↓
Controller (Ch3,7)
↓
DTO Validate (Ch3)
↓
Service Logic (Ch3)
↓
Entity/DB (Ch4,5)
↓
Mapping (Ch7)
↓
Logging/Audit (Ch3,6)
↓
Response (Ch7)
↓
Git/PR (Ch9,10)
↓
Deploy (Ch5,12)
1.7. Transaction trong xử lý API
1.7.1. Nguyên tắc transaction
Mọi thao tác thay đổi dữ liệu nghiệp vụ trong API phải được thực hiện trong transaction nhằm đảm bảo:
-
Tính toàn vẹn dữ liệu
-
Tính nhất quán hệ thống
-
Khả năng rollback khi lỗi
-
Đồng bộ dữ liệu và audit log
Transaction phải được đặt tại Service layer.
1.7.2. Quy định transaction
Transaction:
-
đặt tại Service
-
bao phủ toàn bộ nghiệp vụ
-
bao gồm repository và audit
-
rollback khi exception
Không được đặt transaction tại:
-
Controller
-
Repository
-
Mapper
1.7.3. Ví dụ transaction chuẩn
1.7.4. Quy tắc rollback
Transaction phải rollback khi:
-
BusinessException
-
RuntimeException
-
Database error
-
Validation fail trong service
Không được:
-
ghi audit trước khi save dữ liệu
-
commit từng phần nghiệp vụ
-
xử lý lỗi nhưng vẫn commit
1.8. Security Context trong Service
1.8.1. Khái niệm
Security Context là thông tin người dùng hiện tại sau khi xác thực (JWT / SSO).
Thông tin thường có:
-
userId
-
username
-
role
-
permission
-
tenant
-
organization
1.8.2. Sử dụng trong Service
Service được phép truy cập Security Context để:
-
xác định user thao tác
-
kiểm tra permission
-
ghi audit
-
filter dữ liệu theo user
Ví dụ:
1.8.3. Quy định sử dụng
Không được:
-
tin userId từ request
-
truyền userId từ Controller nếu đã có context
-
bypass permission check
Permission check phải tại Service layer.
1.8.4. Ví dụ kiểm tra quyền
1.9. Xử lý API danh sách (List API)
1.9.1. Nguyên tắc List API
API trả danh sách phải hỗ trợ:
-
pagination
-
sorting
-
filter
Mục tiêu:
-
tránh trả dữ liệu lớn
-
đảm bảo hiệu năng DB
-
hỗ trợ UI paging
1.9.2. Chuẩn request List API
Ví dụ:
Tham số chuẩn:
-
page (bắt đầu từ 0)
-
size
-
sort
-
filter
1.9.3. Chuẩn response List API
1.9.4. Quy định bắt buộc
-
Không trả toàn bộ bảng
-
Pagination bắt buộc với list lớn
-
Repository phải dùng paging query
-
Không load toàn bộ relation
1.10. Gọi hệ thống ngoài trong API
1.10.1. Phạm vi
API có thể cần gọi:
-
SSO
-
External API
-
Message Queue
-
Cache
-
File Storage
1.10.2. Kiến trúc gọi ngoài
Luồng chuẩn:
Service → Integration Client → External System
Ví dụ:
1.10.3. Quy định
Không được gọi external tại:
-
Controller
-
Repository
Phải:
-
gọi trong Service
-
handle lỗi external
-
timeout / retry nếu cần
1.10.4. Xử lý lỗi external
Nếu external fail:
-
map thành BusinessException hoặc SystemException
-
không expose lỗi raw
-
ghi log lỗi
1.11. Monitoring & Metrics trong API
1.11.1. Mục tiêu
Ngoài Logging & Audit, API production cần hỗ trợ:
-
theo dõi hiệu năng
-
theo dõi lỗi
-
theo dõi tải hệ thống
1.11.2. Metrics cần có
-
request count
-
error rate
-
response time
-
DB query time
-
external call time
1.11.3. Trace request
Mỗi request phải có:
-
traceId
-
duration
-
status
TraceId phải liên kết:
-
log
-
audit
-
exception
1.12. Versioning API
1.12.1. Chuẩn version
API phải có version trong URL:
1.12.2. Nguyên tắc version
-
Không thay đổi breaking trong cùng version
-
API cũ phải giữ backward compatibility
-
API mới → tăng version
-
Không reuse version
1.12.3. Ví dụ
1.13. Testing trước merge
1.13.1. Mục tiêu
Đảm bảo API hoạt động đúng trước khi merge và deploy.
1.13.2. Loại test bắt buộc
-
Unit test Service
-
Validation test
-
Error case
-
Integration test API
1.13.3. Quy định
API mới hoặc thay đổi logic phải có test:
-
thành công
-
validation fail
-
business fail
-
permission fail
1.14. Hiệu năng & Database
1.14.1. Nguyên tắc thiết kế DB trong API
API phải đảm bảo:
-
query tối ưu
-
index phù hợp
-
không N+1 query
-
pagination cho list
1.14.2. Các lỗi cần tránh
-
load toàn bộ relation
-
query trong loop
-
select * bảng lớn
-
thiếu index filter
1.14.3. Kiểm tra khi review
Khi review API cần kiểm tra:
-
query có index không
-
list có paging không
-
join có cần thiết không
-
có N+1 không
1.Cấu trúc dự án
1.1. Mục tiêu chương
Chương này quy định cấu trúc dự án chuẩn và phạm vi quản lý mã nguồn giữa Core Team và các đơn vị Partner nhằm:
-
Đảm bảo tính ổn định của hệ thống
-
Tránh xung đột mã nguồn giữa các đơn vị phát triển
-
Chuẩn hóa cách tổ chức code trong toàn dự án
-
Dễ dàng bảo trì, mở rộng và tích hợp hệ thống
1.2. Khái niệm / phạm vi áp dụng
Tài liệu áp dụng cho:
-
Tất cả các dự án sử dụng cấu trúc chuẩn của hệ thống
-
Core Team (đội phát triển lõi)
-
Partner Team (đối tác phát triển module)
Cấu trúc dự án chuẩn:
com.example.demo
├── common/ (thành phần dùng chung)
├── config/ (cấu hình hệ thống)
├── modules/ (các module nghiệp vụ)
└── DemoApplication.java
Ý nghĩa từng khu vực
|
Thư mục |
Vai trò |
Phạm vi sử dụng |
|
common |
Thành phần dùng chung toàn hệ thống |
Core quản lý |
|
config |
Cấu hình hệ thống, security, hạ tầng |
Core quản lý |
|
modules |
Các module nghiệp vụ |
Core + Partner |
1.3. Quy định chính
Phân quyền quản lý code
|
Khu vực |
Đơn vị quản lý |
Quyền chỉnh sửa |
|
common/** |
Core Team |
Partner không được sửa |
|
config/** |
Core Team |
Partner không được sửa |
|
modules/** |
Core + Partner |
Được phép phát triển |
Quy định bắt buộc
Đối tác KHÔNG được phép sửa trực tiếp:
common/**
config/**
Mọi thay đổi trong các khu vực này phải:
-
Tạo yêu cầu thay đổi (Core Change Request)
-
Được Core Team xem xét
-
Core Team phê duyệt và thực hiện
1.4. Cách thực hiện / quy trình
Quy trình thay đổi code dùng chung
Bước 1: Partner phát hiện nhu cầu thay đổi
Bước 2: Tạo ticket với tiêu đề: các phần mềm quản lý công việc liên quan (Jira / Redmine / YouTrack) hoặc nội bộ
[CORE CHANGE REQUEST] Thêm field phone vào user_account
Luồng xử lý:
-
Partner tạo ticket
-
Core Team review
-
Chuyển trạng thái:
|
Trạng thái |
Ý nghĩa |
|
Open |
Ticket mới |
|
Under Review |
Core đang đánh giá |
|
Approved |
Đồng ý thay đổi |
|
Rejected |
Từ chối |
|
Implemented |
Core đã code |
|
Merged |
Đã merge vào develop |
Bước 3: Core Team đánh giá:
-
Phạm vi ảnh hưởng
-
Rủi ro hệ thống
-
Tính cần thiết
Bước 4: Nếu hợp lệ:
-
Core Team thực hiện thay đổi
-
Merge vào nhánh develop
Bước 5: Partner pull code mới về và tiếp tục phát triển
1.5. Ví dụ minh họa
Trường hợp hợp lệ
Partner cần thêm logic trong module planning:
modules/planning/service/PlanningService.java
→ Được phép sửa trực tiếp và tạo PR.
Trường hợp không hợp lệ
Partner muốn sửa:
common/security/JwtAuthenticationFilter.java
→ Không được sửa trực tiếp.
Phải thực hiện:
-
Tạo Core Change Request
-
Chờ Core Team phê duyệt
-
Core Team thực hiện thay đổi
1.6. Checklist áp dụng
Trước khi commit hoặc tạo PR, cần kiểm tra:
-
Code nằm trong modules/**
-
Không sửa common/**
-
Không sửa config/**
-
PR đã được Core Team review (nếu cần)
2.Quy chuẩn phát triển module
2.1. Mục tiêu chương
Chương này quy định cấu trúc chuẩn của mỗi module và trách nhiệm của từng layer nhằm:
-
Tách biệt rõ ràng các tầng xử lý
-
Giảm phụ thuộc giữa các thành phần
-
Dễ bảo trì, mở rộng và test
-
Đảm bảo tính nhất quán giữa các module trong hệ thống
2.2. Khái niệm / phạm vi áp dụng
Quy tắc này áp dụng cho:
-
Tất cả các module trong thư mục modules/**
-
Cả Core Team và Partner Team
-
Tất cả các chức năng mới được phát triển
Cấu trúc chuẩn mỗi module
modules/<module-name>/
controller/
service/
repository/
entity/
dto/
Ý nghĩa từng thành phần
|
Layer |
Vai trò |
ví dụ |
|
controller |
Nhận request từ client và trả response |
@PostMapping public ApiResponse<PlanningResponse> create(@Valid @RequestBody PlanningCreateRequest req) { return ApiResponse.ok(service.create(req)); } |
|
service |
Xử lý logic nghiệp vụ |
public PlanningResponse get(Long id) { PlanningEntity e = repo.findById(id).orElseThrow(() -> new AppException(ErrorCode.NOT_FOUND, HttpStatus.NOT_FOUND, "Planning not found: " + id) ); return toResponse(e); } |
|
repository |
Truy cập và thao tác dữ liệu |
public interface PlanQueryRepository { long count(PlanListFilter filter); List<PlanListItem> list(PlanListFilter filter); } |
|
entity |
Mapping bảng database |
public class PlanningEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; } |
|
dto |
Model request và response |
public class PlanListFilter { private String keyword; private Integer page = 1; // 1-based private Integer size = 20; private String sortBy = "created_at"; private String sortDir = "desc"; public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } public Integer getPage() { return page; } public void setPage(Integer page) { this.page = page; } public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } public String getSortBy() { return sortBy; } public void setSortBy(String sortBy) { this.sortBy = sortBy; } public String getSortDir() { return sortDir; } public void setSortDir(String sortDir) { this.sortDir = sortDir; } } |
2.3. Quy định chính
Trách nhiệm từng layer
Controller
-
Nhận request từ client
-
Gọi service tương ứng
-
Trả response về client
-
Không xử lý logic nghiệp vụ
Service
-
Xử lý logic nghiệp vụ
-
Điều phối repository
-
Chuyển đổi entity ↔ DTO
Repository
-
Truy cập database
-
Thực hiện các thao tác CRUD
-
Không chứa logic nghiệp vụ
Entity
-
Mapping với bảng database
-
Không chứa logic nghiệp vụ phức tạp
DTO
-
Model cho request/response
-
Không gắn trực tiếp với entity
Quy tắc bắt buộc
-
Controller không được chứa logic nghiệp vụ
-
Không trả trực tiếp Entity ra API
-
Luôn dùng DTO cho request/response
-
Response chuẩn toàn hệ thống: ApiResponse<T>
2.4. Cách thực hiện / quy trình
Quy trình phát triển một chức năng mới
Bước 1: Tạo DTO
Ví dụ:
UserCreateRequest
UserResponse
Bước 2: Tạo Entity
Mapping với bảng database:
UserEntity
Bước 3: Tạo Repository
UserRepository
Bước 4: Tạo Service
UserService
Xử lý logic:
-
Validate dữ liệu
-
Gọi repository
-
Mapping entity → DTO
Bước 5: Tạo Controller
UserController
-
Nhận request
-
Gọi service
2.5. Ví dụ minh họa
Ví dụ sai (vi phạm quy tắc)
Controller chứa logic:
@GetMapping("/users")
public List<UserEntity> getAll() {
return userRepository.findAll();
}
Sai vì:
-
Trả Entity trực tiếp
-
Không dùng Service
-
Không dùng ApiResponse
Ví dụ đúng
@GetMapping("/users")
public ApiResponse<List<UserResponse>> getAll() {
return ApiResponse.ok(userService.getAll());
}
Service:
public List<UserResponse> getAll() {
return userRepository.findAll()
.stream()
.map(this::toResponse)
.toList();
}
2.6. Checklist áp dụng
Trước khi commit module mới:
-
Có đủ:
-
controller/
-
service/
-
repository/
-
entity/
-
dto/
-
Controller không chứa logic nghiệp vụ
-
Không trả Entity ra API
-
Tất cả API trả về ApiResponse<T>
-
DTO tách biệt với Entity
3.Coding convention
3.1. Mục tiêu chương
Chương này quy định chuẩn coding và nguyên tắc thiết kế nhằm:
-
Đảm bảo code thống nhất giữa các module và các đơn vị phát triển
-
Giúp code dễ đọc, dễ hiểu và dễ bảo trì
-
Giảm lỗi phát sinh do cách đặt tên hoặc coding không đồng nhất
-
Tăng hiệu quả review và kiểm soát chất lượng code
-
Đảm bảo code tuân thủ nguyên lý thiết kế SOLID
-
Đảm bảo kiến trúc backend Spring Boot nhất quán toàn hệ thống
3.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Toàn bộ source code của hệ thống
-
Core Team và Partner Team
-
Tất cả các module trong
modules/** -
Các thành phần trong
common/**vàconfig/**do Core Team quản lý -
Tất cả service, controller, repository, DTO, entity
3.3. Quy định chính
3.3.1. Quy tắc đặt tên
Các thành phần phải đặt tên theo quy ước thống nhất:
| Thành phần | Quy tắc đặt tên | Ví dụ |
|---|---|---|
| Controller | <Name>Controller |
UserController |
| Service | <Name>Service |
UserService |
| Repository | <Name>Repository |
UserRepository |
| Entity | <Name>Entity |
UserEntity |
| DTO Request | <Name>CreateRequest, <Name>UpdateRequest |
UserCreateRequest |
| DTO Response | <Name>Response |
UserResponse |
| Mapper | <Name>Mapper |
UserMapper |
| Enum | <Name>Enum |
UserStatusEnum |
3.3.2. Quy tắc chung Java
Dùng camelCase cho:
-
Biến
-
Method
Dùng PascalCase cho:
-
Class
-
Interface
-
Enum
Ví dụ:
3.3.3. Quy định về logging
Không được dùng:
Phải dùng logging chuẩn:
3.3.4. Validation dữ liệu đầu vào
Tất cả dữ liệu đầu vào phải được validate bằng annotation.
Annotation chuẩn:
-
@NotNull -
@NotBlank -
@Size -
@Email -
@Pattern
Ví dụ:
3.4. Nguyên lý thiết kế SOLID áp dụng trong dự án
3.4.1. S — Single Responsibility
Một class chỉ có một trách nhiệm.
Quy định dự án:
-
Controller → chỉ xử lý HTTP
-
Service → xử lý nghiệp vụ
-
Repository → truy cập DB
-
Mapper → convert DTO ↔ Entity
Sai:
Đúng:
3.4.2. O — Open/Closed
Code phải mở rộng được nhưng không sửa code cũ.
Áp dụng:
-
Dùng interface Service
-
Không sửa class gốc khi thêm logic
Ví dụ:
Triển khai:
3.4.3. L — Liskov Substitution
Class con có thể thay thế class cha.
Quy định:
-
ServiceImpl phải tuân interface
-
Không throw exception mới trái contract
Sai:
3.4.4. I — Interface Segregation
Không tạo interface quá lớn.
Sai:
Đúng:
3.4.5. D — Dependency Inversion
Phụ thuộc abstraction, không phụ thuộc implementation.
Quy định:
-
Inject interface
-
Không new service
Sai:
Đúng:
3.5. Quy tắc kiến trúc Spring Boot trong dự án
3.5.1. Luồng chuẩn tầng
Không được:
3.5.2. Controller không chứa nghiệp vụ
Sai:
Đúng:
3.5.3. Service không chứa logic HTTP
Sai:
Đúng:
3.5.4. Repository chỉ truy vấn dữ liệu
Không chứa:
-
validation
-
business logic
-
mapping
3.6. Design pattern sử dụng trong hệ thống
3.6.1. Service pattern
Service là tầng nghiệp vụ trung tâm.
3.6.2. DTO pattern
Tách DTO khỏi Entity.
Không trả Entity ra API.
Sai:
Đúng:
3.6.3. Mapper pattern
Convert DTO ↔ Entity.
3.6.4. Exception pattern
Dùng BusinessException thống nhất.
3.7. Cách thực hiện / quy trình
Quy trình tạo DTO đúng chuẩn
Bước 1: Tạo class DTO theo quy tắc đặt tên
Ví dụ:
-
UserCreateRequest
-
UserUpdateRequest
-
UserResponse
Bước 2: Thêm validation annotation
Bước 3: Dùng DTO trong controller
Quy trình logging chuẩn
Bước 1: Khai báo logger trong class
Bước 2: Dùng logger thay cho System.out.println
3.8. Ví dụ minh họa
Trường hợp sai
Sai vì:
-
Tên class không đúng chuẩn
-
Tên method không camelCase
-
Dùng System.out.println
-
Không theo kiến trúc tầng
Trường hợp đúng
Ví dụ DTO sai
Sai vì:
-
Tên class không chuẩn
-
Không có validation
-
Field public
-
Không theo DTO pattern
Ví dụ DTO đúng
3.9. Checklist áp dụng
Trước khi commit hoặc tạo PR:
Naming
-
Controller →
*Controller -
Service →
*Service -
Repository →
*Repository -
Entity →
*Entity -
DTO →
*Request / *Response
Coding
-
Biến và method dùng camelCase
-
Class dùng PascalCase
-
Không dùng System.out.println
-
Dùng logging chuẩn slf4j
Validation
-
DTO có validation annotation
-
Không có field public trong DTO
SOLID
-
Controller không chứa nghiệp vụ
-
Service không chứa HTTP logic
-
Repository chỉ truy vấn DB
-
Inject interface, không new
-
Class có 1 trách nhiệm
Architecture
-
Không Controller → Repository
-
Không trả Entity ra API
-
Có DTO mapping
-
Exception dùng chuẩn hệ thống
3.10. Cấu trúc chuẩn của một hàm xử lý nghiệp vụ
3.10.1. Mục tiêu
Quy định cấu trúc thống nhất của một hàm xử lý nghiệp vụ nhằm:
-
Dễ đọc và dễ review
-
Tách rõ validate – logic – log – exception
-
Tránh thiếu validate hoặc thiếu log
-
Chuẩn hóa xử lý lỗi và response
-
Giúp dev mới đọc code hiểu ngay luồng xử lý
3.10.2. Cấu trúc chuẩn bắt buộc
Một hàm service/controller phải theo thứ tự:
3.10.3. Quy định chi tiết từng phần
1. Validate
-
Validate annotation ở DTO
-
Validate nghiệp vụ ở service
Ví dụ:
2. Log
Phải log:
-
input chính
-
hành động nghiệp vụ
-
lỗi
3. Business logic
Chỉ chứa xử lý nghiệp vụ:
-
mapping
-
tính toán
-
gọi repository
-
gọi service khác
4. Exception handling
Không catch Exception chung chung nếu không xử lý.
Sai:
Đúng:
5. Response
Service:
-
trả DTO
-
hoặc throw BusinessException
Controller:
-
trả ApiResponse
Controller:
3.10.4. Ví dụ hàm sai
Sai vì:
-
Không validate
-
Không log
-
Trả entity
-
Không xử lý lỗi
-
Không theo DTO pattern
3.10.5. Ví dụ hàm đúng chuẩn dự án
3.10.6. Checklist
Khi review hàm service/controller:
-
Có validate nghiệp vụ
-
Có log input chính
-
Không xử lý logic trong controller
-
Không trả Entity
-
Throw BusinessException đúng chuẩn
-
Không catch Exception vô nghĩa
-
Trả DTO / ApiResponse đúng chuẩn
4. Quy định thay đổi cấu trúc dữ liệu (Entity & Database)
4.1. Mục tiêu chương
Chương này quy định cách kiểm soát các thay đổi liên quan đến cấu trúc dữ liệu nhằm:
-
Tránh mất dữ liệu hoặc lỗi hệ thống
-
Đảm bảo tương thích giữa các module
-
Ngăn xung đột schema khi nhiều đơn vị cùng phát triển
-
Bảo vệ các field và bảng dữ liệu chuẩn của hệ thống
4.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Tất cả các entity trong hệ thống
-
Tất cả các bảng database
-
Core Team và Partner Team
-
Mọi thay đổi liên quan đến:
Các loại thay đổi cần kiểm soát
-
Thêm field mới
-
Xóa field
-
Sửa field
-
Đổi kiểu dữ liệu
-
Thay đổi quan hệ entity
-
Thêm/xóa bảng database
4.3. Quy định chính
4.3.1. Không được tự ý thay đổi các field chuẩn
Các field chuẩn hệ thống:
-
id
-
created_at
-
created_by
-
updated_at
-
updated_by
-
deleted / status
-
tenant_id (nếu có)
Quy định bắt buộc
Không được:
-
Xóa field chuẩn
-
Đổi kiểu dữ liệu
-
Đổi tên field
-
Thay đổi ý nghĩa nghiệp vụ của field
Các field này được coi là system fields và được dùng chung cho:
-
Audit
-
Logging
-
Multi-tenant
-
Phân quyền
-
Tích hợp hệ thống
4.3.2. Thêm field mới trong module
Partner chỉ được phép thêm field khi:
-
Phục vụ nghiệp vụ của module
-
Không trùng với dữ liệu core
-
Không phá vỡ cấu trúc hiện tại
-
Có migration script
-
Có mô tả trong Pull Request
-
Được Core Team review
4.3.3. Các thay đổi bắt buộc xin phép Core Team
Các thay đổi sau không được tự ý thực hiện:
-
Đổi kiểu dữ liệu field
-
Xóa field
-
Đổi tên field
-
Thay đổi quan hệ entity
-
Thêm field liên quan:
-
user
-
role
-
permission
-
tenant
-
audit
Tất cả các trường hợp trên phải qua:
Data Model Change Request
4.4. Cách thực hiện / quy trình
Trường hợp 1: Thêm field trong module
Bước 1: Cập nhật entity trong:
modules/<module>/entity/**
Bước 2: Tạo migration script:
V<timestamp>__add_<field>_to_<table>.sql
Bước 3: Tạo Pull Request, trong PR phải có:
-
Mô tả field mới
-
Lý do nghiệp vụ
-
Migration script
Bước 4: Core Team review:
-
Không trùng core data
-
Không phá vỡ hệ thống
Bước 5: Merge vào develop
Trường hợp 2: Thay đổi field hoặc quan hệ entity
Bước 1: Tạo ticket: các phần mềm quản lý công việc liên quan (Jira / Redmine / YouTrack) hoặc nội bộ
[DATA MODEL CHANGE REQUEST] <mô tả thay đổi>
Bước 2: Cung cấp thông tin:
-
Entity bị ảnh hưởng
-
Field thay đổi
-
Kiểu dữ liệu cũ và mới
-
Migration script
-
Lý do thay đổi
Bước 3: Core Team review:
-
Đánh giá ảnh hưởng hệ thống
-
Kiểm tra backward compatibility
Bước 4: Nếu được duyệt:
-
Core Team thực hiện thay đổi
-
Merge vào develop
4.5. Ví dụ minh họa
Trường hợp hợp lệ
Partner thêm field vào entity module:
@Column(name = "PRIORITY")
private Integer priority;
Và có migration:
ALTER TABLE PLANNING ADD PRIORITY INT;
→ Được phép.
Trường hợp không hợp lệ
Partner sửa:
@Column(name = "CREATED_AT")
private String createdAt;
→ Đổi kiểu dữ liệu từ timestamp sang string.
→ Không được phép.
Phải tạo:
[DATA MODEL CHANGE REQUEST]
Trường hợp cần xin phép
Partner muốn:
-
Xóa field status
-
Đổi tên description → detail
-
Thêm quan hệ với bảng user_account
4.6. Checklist áp dụng
Trước khi commit hoặc tạo PR:
-
Có thay đổi field chuẩn không?
-
Nếu có → phải tạo Data Model Change Request
-
Có đổi kiểu dữ liệu field không?
-
Nếu có → phải xin phép Core Team
-
Có migration script chưa?
-
Field mới có trùng dữ liệu core không?
-
PR đã mô tả rõ thay đổi chưa?
5.Quy định về Database, Schema và Migration
5.1. Mục tiêu chương
Chương này quy định cách quản lý cấu trúc database và các thay đổi schema nhằm:
-
Đảm bảo tính ổn định của dữ liệu hệ thống
-
Tránh xung đột schema giữa các module và các đơn vị phát triển
-
Đảm bảo khả năng triển khai tự động qua các môi trường
-
Kiểm soát lịch sử thay đổi database
5.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Toàn bộ database của hệ thống
-
Core Team và Partner Team
-
Tất cả các thay đổi liên quan đến:
-
Bảng dữ liệu
-
Cột dữ liệu
-
Constraint
-
Index
-
Trigger
Hệ thống phân loại bảng dữ liệu thành hai nhóm:
1. Core tables (dùng chung toàn hệ thống)
Bao gồm các bảng:
-
app_user
-
theme_config
-
feature_management
Đây là các bảng dữ liệu lõi, được dùng chung cho:
-
Xác thực
-
Phân quyền
-
Cấu hình hệ thống
2. Module tables
Bao gồm:
-
Các bảng thuộc từng module riêng
-
Nằm trong phạm vi nghiệp vụ của module
Ví dụ:
-
planning
-
document
-
task
-
notification
5.3. Quy định chính
5.3.1. Quy định với Core tables
Partner không được phép:
-
Thay đổi cấu trúc bảng
-
Thêm cột
-
Xóa cột
-
Đổi kiểu dữ liệu
-
Sửa constraint
-
Sửa index
-
Sửa trigger
Mọi thay đổi liên quan đến core tables phải thông qua:
DB Core Change Request -> sử dụng jira/… hoặc các phần mềm quản lý công việc nội bộ
Và do Core Team thực hiện.
5.3.2. Quy định với Module tables
Partner được phép:
-
Tạo bảng mới cho module
-
Thêm cột
-
Sửa cấu trúc bảng module
Nhưng phải tuân thủ:
-
Không ảnh hưởng core tables
-
Có migration script
-
Có mô tả rõ trong Pull Request
-
Được Core Team review
5.3.3. Migration bắt buộc
Mọi thay đổi database phải tuân thủ các nguyên tắc sau:
-
Không sửa trực tiếp database production
-
Không chỉnh sửa thủ công trên DB staging
-
Tất cả thay đổi phải qua migration script
-
Migration phải được commit vào source code
Công cụ sử dụng:
-
Flyway hoặc Liquibase
Format migration
Tên file migration:
V<timestamp>__<description>.sql
Ví dụ:
V20260209__create_planning_table.sql
V20260210__add_priority_to_planning.sql
5.4. Cách thực hiện / quy trình
Trường hợp 1: Thêm hoặc sửa bảng trong module
Bước 1: Cập nhật entity trong:
modules/<module>/entity/**
Bước 2: Tạo migration script:
V<timestamp>__<description>.sql
Bước 3: Commit:
-
Entity
-
Migration script
Bước 4: Tạo Pull Request
Bước 5: Core Team review:
-
Migration hợp lệ
-
Không ảnh hưởng core tables
Bước 6: Merge vào develop
Trường hợp 2: Thay đổi core tables
Bước 1: Tạo ticket:
[DB CORE CHANGE REQUEST] <mô tả thay đổi>
Bước 2: Cung cấp thông tin:
-
Bảng bị ảnh hưởng
-
Cột thay đổi
-
Kiểu dữ liệu
-
Migration script đề xuất
-
Lý do thay đổi
Bước 3: Core Team review
Bước 4: Nếu được duyệt:
-
Core Team thực hiện migration
Merge vào develop
5.5. Ví dụ minh họa
Trường hợp hợp lệ
Partner thêm bảng mới:
CREATE TABLE PLANNING (
ID BIGINT PRIMARY KEY,
NAME VARCHAR(255),
DESCRIPTION VARCHAR(1000)
);
→ Thuộc module table → được phép.
Trường hợp không hợp lệ
Partner chạy trực tiếp trên production:
ALTER TABLE USER_ACCOUNT ADD PHONE VARCHAR(20);
→ Sai quy định vì:
-
Sửa core table
-
Sửa trực tiếp DB production
-
Không có migration
Trường hợp cần xin phép
Partner muốn:
ALTER TABLE ROLE ADD DESCRIPTION VARCHAR(255);
→ Đây là core table.
Phải tạo: trên phần mềm quản lý công việc nội bộ hoặc phần mềm nghiệp vụ tương đương
[DB CORE CHANGE REQUEST]
5.6. Checklist áp dụng
Trước khi commit hoặc tạo PR:
-
Có thay đổi database không?
-
Nếu có → phải có migration script
-
Có sửa core table không?
-
Nếu có → phải tạo DB Core Change Request
-
Migration có đúng format tên file không?
-
Không sửa trực tiếp DB production
-
Migration đã được commit vào source code
5.7. Quy định thay đổi cấu trúc dữ liệu (Entity & Database)
5.7.1. Mục tiêu chương
Chương này quy định cách kiểm soát các thay đổi liên quan đến cấu trúc dữ liệu nhằm:
-
Tránh mất dữ liệu hoặc lỗi hệ thống
-
Đảm bảo tương thích giữa các module
-
Ngăn xung đột schema khi nhiều đơn vị cùng phát triển
-
Bảo vệ các field và bảng dữ liệu chuẩn của hệ thống
4.7.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Tất cả các entity trong hệ thống
-
Tất cả các bảng database
-
Core Team và Partner Team
-
Mọi thay đổi liên quan đến:
Các loại thay đổi cần kiểm soát
-
Thêm field mới
-
Xóa field
-
Sửa field
-
Đổi kiểu dữ liệu
-
Thay đổi quan hệ entity
-
Thêm/xóa bảng database
5.7.3. Quy định chính
5.7.3.1. Không được tự ý thay đổi các field chuẩn
Các field chuẩn hệ thống:
-
id
-
created_at
-
created_by
-
updated_at
-
updated_by
-
deleted / status
-
tenant_id (nếu có)
Quy định bắt buộc
Không được:
-
Xóa field chuẩn
-
Đổi kiểu dữ liệu
-
Đổi tên field
-
Thay đổi ý nghĩa nghiệp vụ của field
Các field này được coi là system fields và được dùng chung cho:
-
Audit
-
Logging
-
Multi-tenant
-
Phân quyền
-
Tích hợp hệ thống
5.7.3.2. Thêm field mới trong module
Partner chỉ được phép thêm field khi:
-
Phục vụ nghiệp vụ của module
-
Không trùng với dữ liệu core
-
Không phá vỡ cấu trúc hiện tại
-
Có migration script
-
Có mô tả trong Pull Request
-
Được Core Team review
5.7.3.3. Các thay đổi bắt buộc xin phép Core Team
Các thay đổi sau không được tự ý thực hiện:
-
Đổi kiểu dữ liệu field
-
Xóa field
-
Đổi tên field
-
Thay đổi quan hệ entity
-
Thêm field liên quan:
-
user
-
role
-
permission
-
tenant
-
audit
Tất cả các trường hợp trên phải qua:
Data Model Change Request
5.7.4. Cách thực hiện / quy trình
Trường hợp 1: Thêm field trong module
Bước 1: Cập nhật entity trong:
modules/<module>/entity/**
Bước 2: Tạo migration script:
V<timestamp>__add_<field>_to_<table>.sql
Bước 3: Tạo Pull Request, trong PR phải có:
-
Mô tả field mới
-
Lý do nghiệp vụ
-
Migration script
Bước 4: Core Team review:
-
Không trùng core data
-
Không phá vỡ hệ thống
Bước 5: Merge vào develop
Trường hợp 2: Thay đổi field hoặc quan hệ entity
Bước 1: Tạo ticket: các phần mềm quản lý công việc liên quan (Jira / Redmine / YouTrack) hoặc nội bộ
[DATA MODEL CHANGE REQUEST] <mô tả thay đổi>
Bước 2: Cung cấp thông tin:
-
Entity bị ảnh hưởng
-
Field thay đổi
-
Kiểu dữ liệu cũ và mới
-
Migration script
-
Lý do thay đổi
Bước 3: Core Team review:
-
Đánh giá ảnh hưởng hệ thống
-
Kiểm tra backward compatibility
Bước 4: Nếu được duyệt:
-
Core Team thực hiện thay đổi
-
Merge vào develop
5.7.5. Ví dụ minh họa
Trường hợp hợp lệ
Partner thêm field vào entity module:
@Column(name = "PRIORITY")
private Integer priority;
Và có migration:
ALTER TABLE PLANNING ADD PRIORITY INT;
→ Được phép.
Trường hợp không hợp lệ
Partner sửa:
@Column(name = "CREATED_AT")
private String createdAt;
→ Đổi kiểu dữ liệu từ timestamp sang string.
→ Không được phép.
Phải tạo:
[DATA MODEL CHANGE REQUEST]
Trường hợp cần xin phép
Partner muốn:
-
Xóa field status
-
Đổi tên description → detail
-
Thêm quan hệ với bảng user_account
5.7.6. Checklist áp dụng
Trước khi commit hoặc tạo PR:
-
Có thay đổi field chuẩn không?
-
Nếu có → phải tạo Data Model Change Request
-
Có đổi kiểu dữ liệu field không?
-
Nếu có → phải xin phép Core Team
-
Có migration script chưa?
-
Field mới có trùng dữ liệu core không?
-
PR đã mô tả rõ thay đổi chưa?
6.Audit Log & System Metadata
6.1. Mục tiêu chương
Chương này quy định cách quản lý dữ liệu audit nhằm:
-
Đảm bảo khả năng truy vết toàn bộ hoạt động hệ thống
-
Phục vụ kiểm tra, giám sát và điều tra sự cố
-
Đáp ứng yêu cầu kiểm toán và tuân thủ
-
Bảo vệ dữ liệu hệ thống khỏi việc chỉnh sửa trái phép
6.2. Khái niệm / phạm vi áp dụng
Audit log là dữ liệu ghi nhận:
-
Hành động của người dùng
-
Thay đổi dữ liệu quan trọng
-
Sự kiện hệ thống
-
Hoạt động bảo mật
Các bảng audit:
-
audit_log
-
action_history
-
system_event
Các bảng này được coi là dữ liệu core của hệ thống.
Quy định này áp dụng cho:
-
Tất cả module trong hệ thống
-
Core Team và Partner Team
Mọi thay đổi liên quan đến audit
6.3. Quy định chính
Partner không được phép:
-
Thay đổi cấu trúc bảng audit
-
Thêm hoặc xóa cột trong bảng audit
-
Xóa dữ liệu audit
-
Chỉnh sửa dữ liệu audit thủ công
-
Thay đổi logic ghi log
Các bảng audit được coi là:
Core system data
Mọi thay đổi liên quan đến:
-
Cấu trúc bảng audit
-
Logic ghi log
-
Cơ chế lưu trữ audit
phải được:
Core Team phê duyệt
6.4. Cách thực hiện / quy trình
Trường hợp 1: Module cần ghi thêm audit
Bước 1: Sử dụng cơ chế audit có sẵn của hệ thống
Ví dụ:
-
AuditService
-
Annotation audit
-
Event audit
Bước 2: Không được tự tạo bảng audit riêng
Bước 3: Nếu cần mở rộng dữ liệu audit:
Tạo ticket:
[AUDIT CHANGE REQUEST] <mô tả thay đổi>
Bước 4: Core Team review:
-
Xem xét nhu cầu
-
Đánh giá ảnh hưởng hệ thống
-
Quyết định phương án mở rộng
Trường hợp 2: Cần thay đổi cấu trúc bảng audit
Bước 1: Tạo ticket:
[DB CORE CHANGE REQUEST] Audit table change
Bước 2: Cung cấp thông tin:
-
Bảng audit bị ảnh hưởng
-
Field cần thêm/sửa
-
Lý do thay đổi
-
Migration script
Bước 3: Core Team review và quyết định
6.5. Ví dụ minh họa
Trường hợp hợp lệ
Module planning muốn ghi log khi tạo kế hoạch:
auditService.logCreate("PLANNING", planningId, userId);
→ Sử dụng cơ chế audit có sẵn → hợp lệ.
Trường hợp không hợp lệ
Partner tự tạo bảng:
CREATE TABLE planning_audit (
id BIGINT,
action VARCHAR(50)
);
→ Sai quy định vì:
-
Tự tạo bảng audit riêng
-
Không dùng hệ thống audit chung
Trường hợp bị cấm
Partner chạy trực tiếp:
DELETE FROM audit_log WHERE created_at < '2024-01-01';
→ Không được phép xóa dữ liệu audit.
6.6. Checklist áp dụng
Trước khi commit hoặc tạo PR:
-
Có thay đổi bảng audit không?
-
Nếu có → phải xin Core Team
-
Có xóa dữ liệu audit không?
-
Nếu có → không được phép
-
Có tự tạo bảng audit riêng không?
-
Nếu có → phải chuyển sang audit chung
-
Có thay đổi logic audit không?
-
Nếu có → phải tạo Audit Change Request
7.API Design & Response Standard
7.1. Mục tiêu chương
Chương này quy định chuẩn API và định dạng response nhằm:
-
Đảm bảo tính nhất quán giữa các module
-
Dễ tích hợp giữa FE và BE
-
Hỗ trợ versioning API trong tương lai
-
Giảm rủi ro khi thay đổi cấu trúc dữ liệu
7.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Tất cả API trong hệ thống
-
Core Team và Partner Team
-
Tất cả module trong thư mục modules/**
Mọi API phải tuân theo:
-
Chuẩn base path
-
Chuẩn định dạng response
7.3. Quy định chính
7.3.1. Chuẩn Base Path
Tất cả API phải có dạng:
/api/v1/<module-name>
vd: http://localhost:8080/api/v1/auth/config
Trong đó:
-
api: tiền tố chung của hệ thống
-
v1: version của API
-
<module-name>: tên module nghiệp vụ
Ví dụ base path hợp lệ
|
Module |
Base path |
|
auth |
/api/v1/auth |
|
planning |
/api/v1/planning |
|
document |
/api/v1/document |
|
user |
/api/v1/user |
7.3.2. Chuẩn Response
Tất cả API phải trả về:
ApiResponse<T>
Không được trả:
-
Entity
-
DTO
-
List
-
Map
-
String
-
Boolean
trực tiếp ra API.
Cấu trúc chuẩn của ApiResponse
Ví dụ:
{
"success": true,
"message": "OK",
"data": {
"id": 1,
"name": "Test"
}
}
Hoặc với danh sách:
{
"success": true,
"message": "OK",
"data": [
{ "id": 1, "name": "A" },
{ "id": 2, "name": "B" }
]
}
7.4. Cách thực hiện / quy trình
Bước 1: Tạo controller theo base path
Ví dụ:
@RestController
@RequestMapping("/api/v1/planning")
public class PlanningController {
}
Bước 2: Service trả DTO
public PlanningResponse getById(Long id) {
// xử lý nghiệp vụ
}
Bước 3: Controller trả ApiResponse
@GetMapping("/{id}")
public ApiResponse<PlanningResponse> getById(@PathVariable Long id) {
return ApiResponse.ok(planningService.getById(id));
}
7.5. Ví dụ minh họa
Trường hợp sai
@GetMapping("/planning")
public List<PlanningEntity> getAll() {
return planningRepository.findAll();
}
Sai vì:
-
Trả entity trực tiếp
-
Không dùng ApiResponse
-
Bỏ qua service layer
Trường hợp đúng
@GetMapping
public ApiResponse<List<PlanningResponse>> getAll() {
return ApiResponse.ok(planningService.getAll());
}
Trường hợp sai về base path
@RequestMapping("/planning")
→ Sai vì thiếu:
/api/v1/
7.6. Checklist áp dụng
Trước khi commit hoặc tạo PR:
-
API có đúng base path /api/v1/<module> không?
-
Controller có trả ApiResponse<T> không?
-
Có trả raw object không?
-
Nếu có → phải sửa
-
Có trả Entity trực tiếp không?
-
Nếu có → phải chuyển sang DTO
-
API có đúng version (v1) không?
8. Cơ chế xác thực & tích hợp SSO (WSO2)
8.1. Mục tiêu chương
Quy định cơ chế xác thực linh hoạt giữa:
-
Local Login
-
SSO qua WSO2 IS
Nhằm:
-
Phục vụ dev/test
-
Hỗ trợ định danh tập trung khi triển khai
8.2. Khái niệm / phạm vi áp dụng
Hai chế độ xác thực:
|
Chế độ |
Mô tả |
|
Local |
Login nội bộ |
|
WSO2 |
Login qua SSO OIDC |
8.3. Quy định chính
Nguyên tắc chung
Logic xác thực nằm trong:
modules/auth
common/security
-
Partner không được sửa logic xác thực
-
Không thêm cơ chế login khác
Cấu hình chế độ đăng nhập
auth.type = local
auth.type = wso2
Local Login
-
Xác thực username/password
-
Dữ liệu ở bảng user_account
-
BE sinh token
WSO2 SSO flow
-
FE redirect sang WSO2
-
User login
-
WSO2 trả access_token
-
BE validate token
Quy tắc FE
-
FE đọc authType từ backend
-
local → hiển thị form login
-
wso2 → auto redirect
Không được hardcode.
Quy tắc BE
-
Tất cả API qua security filter
-
Không bypass auth
Không hardcode user
8.4. Quy trình thêm FE mới vào SSO
-
Partner cung cấp:
-
Domain FE
-
Redirect URI
-
Môi trường
-
Core tạo OAuth client
-
Cấp client_id, scope
8.5. Checklist tích hợp xác thực
9.Git Workflow & Pull Request
Chú ý: tham chiếu sang tài liệu để theo dõi rõ ràng đầy đủ hơn: https://docs.lifetex.vn/books/quy-dinh-git-workflow-va-quy-uoc-code c
9.1. Mục tiêu chương
Chương này quy định chuẩn commit và quy trình merge code nhằm:
-
Đảm bảo lịch sử thay đổi rõ ràng, dễ truy vết
-
Giảm xung đột giữa các nhóm phát triển
-
Đảm bảo chất lượng code trước khi đưa vào nhánh chính
-
Chuẩn hóa quy trình phát triển giữa Core Team và Partner
9.2. Khái niệm / phạm vi áp dụng
Quy định này áp dụng cho:
-
Tất cả repository của dự án
-
Core Team và Partner Team
-
Mọi commit và Pull Request (PR)
Quy trình phát triển tuân theo:
-
Chuẩn format commit
-
Chiến lược branch
Điều kiện merge bắt buộc
9.3. Quy định chính
9.3.1. Format commit
Tất cả commit phải theo format:
<type>: <description>
Trong đó:
-
<type>: loại thay đổi
-
<description>: mô tả ngắn gọn nội dung thay đổi
Ví dụ commit hợp lệ
feat: add planning API
fix: validate file upload
refactor: optimize planning service
docs: update API guideline
test: add unit test for planning service
chore: update dependency versions
Type hợp lệ
|
Type |
Ý nghĩa |
|
feat |
Thêm chức năng mới |
|
fix |
Sửa lỗi |
|
refactor |
Tối ưu, không đổi logic |
|
docs |
Cập nhật tài liệu |
|
test |
Thêm hoặc sửa test |
|
chore |
Thay đổi cấu hình, build, dependency |
9.3.2. Branch strategy
Hệ thống sử dụng mô hình branch chuẩn:
|
Branch |
Mục đích |
|
main |
Bản stable, dùng cho production |
|
develop |
Bản tích hợp, nơi merge các feature |
|
feature/* |
Phát triển chức năng mới |
|
fix/* |
Sửa lỗi |
Quy tắc làm việc với branch
-
Không commit trực tiếp vào main
-
Không commit trực tiếp vào develop
-
Mọi thay đổi phải qua Pull Request
-
Branch phải được đặt tên đúng quy tắc
Ví dụ tên branch hợp lệ
feature/planning-create-api
feature/document-upload
fix/login-null-pointer
fix/planning-date-validation
9.3.3. Điều kiện merge Pull Request
Pull Request chỉ được merge khi đáp ứng đầy đủ các điều kiện:
-
Build thành công
Không sửa:
common/**
config/**
Có review từ Core Team
9.4. Cách thực hiện / quy trình
Quy trình phát triển tính năng
Bước 1: Tạo branch từ develop
git checkout develop
git pull
git checkout -b feature/planning-create-api
Bước 2: Thực hiện commit theo chuẩn
git commit -m "feat: add planning create API"
Bước 3: Push branch lên remote
git push origin feature/planning-create-api
Bước 4: Tạo Pull Request vào develop
Bước 5: Core Team review
Bước 6: Nếu đạt yêu cầu → merge vào develop
Quy trình sửa lỗi
Bước 1: Tạo branch fix
git checkout develop
git checkout -b fix/planning-null-error
Bước 2: Commit
git commit -m "fix: handle null planning name"
Bước 3: Tạo PR và chờ review
9.5. Ví dụ minh họa
Trường hợp commit sai
Sai vì:
-
Không theo format chuẩn
-
Không có type
Trường hợp commit đúng
fix: handle null planning name
Trường hợp merge sai
Partner:
-
Commit trực tiếp vào develop
-
Không tạo PR
-
Không có review
→ Vi phạm quy trình.
Trường hợp merge đúng
-
Tạo branch feature/planning-api
-
Commit theo chuẩn
-
Tạo PR vào develop
-
Core Team review
-
Build pass
-
Merge
9.6. Checklist áp dụng
Trước khi tạo Pull Request:
-
Commit đúng format <type>: <description>
-
Branch đúng quy tắc feature/* hoặc fix/*
-
Không commit trực tiếp vào main hoặc develop
-
Build thành công
-
Không sửa:
-
common/**
-
config/**
-
shared entity
-
PR đã được Core Team review
10.Checklist kiểm tra trước khi merge
10.1. Mục tiêu chương
Chương này quy định checklist bắt buộc trước khi merge code nhằm:
-
Đảm bảo chất lượng code trước khi tích hợp
-
Tránh vi phạm các quy định về kiến trúc và dữ liệu
-
Giảm rủi ro lỗi khi build hoặc triển khai
-
Chuẩn hóa quy trình review giữa Core Team và Partner
10.2. Khái niệm / phạm vi áp dụng
Checklist này áp dụng cho:
-
Tất cả Pull Request (PR)
-
Core Team và Partner Team
-
Mọi module trong hệ thống
Checklist được dùng trong:
-
Code review
-
Kiểm tra trước khi merge vào develop
Kiểm tra trước khi release
10.3. Quy định chính
Pull Request chỉ được phép merge khi đáp ứng đầy đủ các điều kiện sau:
Code nằm trong khu vực được phép:
modules/**
- Không sửa các khu vực bị cấm:
common/**
config/**
common/entity/**
- Nếu có thay đổi database:
-
Phải có migration script
-
API phải đúng chuẩn:
/api/v1/<module-name>
-
Response phải dùng:
ApiResponse<T>
7.Build phải thành công
10.4. Cách thực hiện / quy trình
Quy trình kiểm tra trước khi merge
Bước 1: Dev hoàn thành feature hoặc fix bug
Bước 2: Tạo Pull Request vào develop
Bước 3: Dev tự kiểm tra checklist
Bước 4: Core Team review theo checklist
Bước 5: Nếu đạt yêu cầu → merge
Nếu không đạt:
-
PR bị reject
-
Dev phải sửa lại theo checklist
10.5. Ví dụ minh họa
Trường hợp hợp lệ
PR:
Chỉ sửa code trong:
modules/planning/**
- Có migration: V20260210__add_priority_to_planning.sql
- API: /api/v1/planning
-
Build thành công
→ Được merge.
Trường hợp không hợp lệ
PR:
Sửa file:
common/entity/UserEntity.java
→ Vi phạm quy định shared entity.
→ PR bị từ chối.
Trường hợp bị từ chối do thiếu migration
PR:
Thêm field trong entity:
private Integer priority;
-
Không có migration SQL
→ PR bị reject.
10.6. Checklist áp dụng
Dev phải tick đủ các mục sau trước khi merge:
[ ] Code nằm trong modules/**
[ ] Không sửa common/**
[ ] Không sửa config/**
[ ] Có migration nếu thay đổi DB
[ ] API đúng chuẩn /api/v1/
[ ] Response dùng ApiResponse
[ ] Build thành công
Core Team chỉ merge khi checklist đạt đầy đủ.
11.Quy trình phối hợp & quản lý thay đổi liên nhóm
11.1. Mục tiêu chương
Chương này quy định cách phối hợp giữa nhiều đơn vị phát triển nhằm:
-
Tránh xung đột giữa FE, BE và Database
-
Đảm bảo tích hợp ổn định
-
Giữ tính tương thích giữa các module
-
Kiểm soát các thay đổi ảnh hưởng hệ thống
11.2. Khái niệm / phạm vi áp dụng
Áp dụng khi:
-
Có nhiều đơn vị cùng phát triển
-
FE và BE tách source
-
Nhiều FE dùng chung BE
-
BE tách thành nhiều service
Mọi thay đổi liên quan:
-
API contract
-
Entity/Database
-
Auth
-
Domain/CORS
đều phải thông qua Core Team.
11.3. Quy định chính
Nguyên tắc chung
-
Dùng contract-first (OpenAPI là nguồn chuẩn)
-
Mọi thay đổi API hoặc DB phải được kiểm soát
-
Mọi thay đổi breaking phải qua Core Team
Trường hợp FE và BE khác source, dùng chung DB
Rủi ro:
-
Sai contract API
-
Response làm FE vỡ
-
Migration xung đột
Quy định:
-
BE thay đổi API/DB phải update OpenAPI
-
Mọi thay đổi DB phải có migration
-
Staging dùng DB chung
Quy trình:
-
FE tạo ticket: API CONTRACT ISSUE
-
BE/Core xác nhận
-
Fix backward compatible hoặc tạo API v2
Trường hợp FE và BE dùng DB riêng khi dev
Quy định:
-
Có DB baseline chung
-
Staging dùng DB chung
Quy trình:
-
Nếu staging lỗi → so version migration
-
Không cho merge nếu thiếu migration
Trường hợp nhiều FE dùng chung một BE
Quy định:
-
Dùng IdP chung (WSO2/Keycloak)
-
Mỗi FE là một OAuth client riêng
-
Gọi API bằng JWT
Quy trình:
-
FE đăng ký client_id
-
Core cấu hình redirectUri, scope
-
Core cấp quyền
Trường hợp FE chung source, BE nhiều service
Quy định:
-
FE cấu hình baseURL theo service
-
Auth dùng token chung
-
CORS do Core Team quản lý
Quy trình:
-
Thêm service → tạo Integration Checklist
-
Core cấu hình CORS và token audience
Trường hợp thay đổi response làm FE vỡ
Quy định:
-
Chỉ được thêm field (non-breaking)
-
Không đổi kiểu dữ liệu
-
Không rename field
-
Breaking change phải tạo /api/v2
Quy trình:
-
Tạo BREAKING CHANGE REQUEST
-
Core duyệt
-
Thông báo FE
Trường hợp xung đột entity/model
Quy định:
-
Entity dùng chung → coi là shared model
-
Phải qua Data Model Change Request
Quy trình:
-
Partner đề xuất field + migration
-
Core review
-
Approve hoặc yêu cầu sửa
Trường hợp migration xung đột
Quy định:
-
Không sửa migration đã merge
-
Tạo migration mới để fix forward
Quy trình:
-
Rebase
-
Tạo migration mới
-
Test staging
Trường hợp seed/master data bị sửa
Quy định:
-
Seed core do Core Team quản lý
-
Partner chỉ được đề xuất
Quy trình:
-
Tạo MASTER DATA REQUEST
-
Core duyệt và triển khai
11.4. Quy trình triển khai tính năng nhiều tầng
-
Tạo ticket Feature
-
Chốt API contract (OpenAPI)
-
Chốt entity/migration
-
BE implement
-
FE integrate
-
Test staging
-
Release
11.5.Ví dụ minh họa
1. bảng mô tả các môi trường hệ thống:
| Env | FE URL | BE URL | DB | Auth |
|---|---|---|---|---|
| dev | http://localhost:4200 | http://localhost:8080 | local | mock |
| staging | https://staging.app.vn | https://staging.api.vn | shared | WSO2 thật |
| prod | https://app.vn | https://api.vn | prod | WSO2 thật |
12. Connect Database & mẫu CRUD & switch Oracle/MSSQL
12.Quy định kết nối Database và Message Queue
12.1. Mục tiêu chương
Chuẩn hóa kết nối DB và Message Queue nhằm:
-
Tránh hardcode cấu hình
-
Đảm bảo tính ổn định hạ tầng
-
Kiểm soát tài nguyên hệ thống
12.2. Khái niệm / phạm vi áp dụng
Áp dụng cho:
-
Database
-
RabbitMQ
-
Kafka
-
Core Team và Partner
12.3. Quy định chính
Kết nối Database
Cấu hình datasource tại:
config/**
application-*.yml
-
Không hardcode:
-
host
-
port
-
user
-
password
-
Không tạo JDBC connection thủ công
-
Mọi truy cập DB qua repository/service
Message Queue
-
Kết nối queue do Core Team quản lý
Cấu hình tại:
config/**
common/messaging/**
Partner không được:
-
Tự tạo connection
-
Hardcode config
-
Tự tạo queue/topic
Chuẩn đặt tên queue/topic
<system>.<module>.<purpose>
Ví dụ:
core.audit.log
planning.project.created
auth.user.synced
12.4. Quy trình tạo queue/topic
Tạo ticket:
[QUEUE REQUEST] <module> - <purpose>
-
Cung cấp:
-
module
-
mục đích
-
producer
-
consumer
-
retry/DLQ
Core tạo queue và cấp quyền
12.5. Checklist DB & Queue
Database:
-
Không hardcode kết nối
-
Có migration khi đổi DB
Queue:
-
Queue do Core cấp
-
Có log và retry/DLQ
13.1. Mục tiêu chương
Thiết kế kiến trúc đa database nhằm:
-
Tách logic nghiệp vụ và truy vấn
-
Switch Oracle/MSSQL bằng cấu hình
-
Không sửa service khi đổi DB
-
Áp dụng nguyên tắc SOLID
13.2. Khái niệm / phạm vi áp dụng
Áp dụng cho:
-
Các module hỗ trợ đa DB
-
Các hệ thống cần deploy trên:
-
Oracle
-
SQL Server
13.3. Quy định chính
Nguyên tắc thiết kế
-
Service không phụ thuộc DB
-
Query tách theo dialect:
-
Oracle
-
MSSQL
-
Repository chỉ thực thi SQL
-
Switch DB bằng config:
db.vendor = oracle | mssql
Cấu trúc khuyến nghị
modules/<module>/
controller/
service/
repository/
query/
QueryProvider.java
OracleQueryProvider.java
SqlServerQueryProvider.java
entity/
dto/
Quy định đa DB
-
Không viết SQL trong Service/Controller
-
Không if/else theo DB trong Service
-
Khác biệt DB chỉ nằm ở QueryProvider
-
Dùng named parameters: :param
13.4. Cách thực hiện / quy trình
Khi thay đổi nghiệp vụ
-
Sửa Service
-
Cập nhật query tương ứng trong provider
Khi khác DB
-
Chỉ sửa query trong:
-
OracleQueryProvider
-
SqlServerQueryProvider
-
Không sửa Service
Khi tạo Pull Request
PR phải:
-
Ghi rõ ảnh hưởng
-
Có smoke test trên env tương ứng
13.5. Ví dụ minh họa
Cấu hình
db.vendor = mssql
Hệ thống tự inject:
SqlServerQueryProvider
Ví dụ sai
if (dbType.equals("oracle")) {
// SQL
} else {
// SQL
}
Sai vì logic DB nằm trong Service.
Ví dụ đúng
Service:
queryProvider.getFindAllPlanningSql();
QueryProvider quyết định SQL theo DB.
13.6. Checklist áp dụng
-
Service không chứa SQL
-
Không if/else theo DB trong service
-
SQL nằm trong QueryProvider
-
Query dùng named parameters
-
PR có test trên DB tương ứng
13.Swagger API Documentation & JWT Testing
13.1. Mục tiêu chương
Chương này quy định cách:
-
Tạo tài liệu API bằng Swagger/OpenAPI
-
Cấu hình Swagger cho Spring Boot
-
Tích hợp xác thực JWT vào Swagger
-
Test API có auth trực tiếp trên Swagger UI
Mục tiêu:
-
Dev và QA có thể test API nhanh
-
Chuẩn hóa tài liệu API
-
Tránh test sai do thiếu token
-
Đồng nhất cách dùng Swagger giữa các team
13.2. Truy cập Swagger UI
Sau khi chạy service:
Hoặc:
Swagger hiển thị danh sách API theo controller.
13.3. Cấu hình Swagger trong Spring Boot
Dependency Maven:
13.3.1. Cấu hình OpenAPI + JWT
File:
13.4. Đánh dấu API cần JWT trong Controller
Controller cần auth:
Swagger sẽ hiển thị icon:
13.5. Cấu hình Spring Security cho Swagger
Swagger UI phải được phép truy cập không cần auth:
API business:
13.6. Test API có JWT trên Swagger (Step-by-Step)
Bước 1. Login lấy JWT
Gọi API login:
Response:
Bước 2. Mở Swagger
Bước 3. Click Authorize
Góc phải Swagger:
Click vào.
Bước 4. Nhập JWT
Nhập:
Lưu ý:
-
Phải có chữ Bearer
-
Có khoảng trắng sau Bearer
Ví dụ đúng:
Bước 5. Authorize
Click:
Swagger sẽ lưu token cho toàn bộ API.
Bước 6. Test API
Chọn API có 🔒:
Click:
Swagger gửi request:
13.7. Kiểm tra Swagger đã gửi token chưa
Trong Swagger phần Curl phải có:
Nếu không có → chưa Authorize.
13.8. Lỗi thường gặp
403 Forbidden
Nguyên nhân:
-
Chưa nhập token
-
Token sai
-
Token hết hạn
-
API cần auth nhưng Swagger chưa Authorize
Không thấy nút Authorize
Nguyên nhân:
-
Chưa cấu hình SecurityScheme
-
Swagger config sai
-
Cache browser
Khắc phục:
Swagger call được API không cần token
Nguyên nhân:
Security config permitAll API.
Ví dụ:
Swagger không cần JWT.
13.9. Quy định chuẩn sử dụng Swagger trong dự án
Controller cần auth:
Controller public:
không cần annotation.
API test phải:
13.10. Quy định commit & PR
API mới phải:
-
Hiển thị trên Swagger
-
Có request/response schema
-
Có SecurityRequirement nếu cần auth
-
Test được trên Swagger
PR bị reject nếu:
-
API không có Swagger
-
Swagger lỗi
-
Không test được
13.11. Checklist Swagger cho Dev
Trước khi merge:
-
Swagger mở được
-
API hiển thị
-
Authorize hoạt động
-
JWT call OK
-
Response đúng schema
13.12. Best Practice
Không permitAll API production.
Swagger chỉ permit:
JWT luôn test qua Authorize.
Chương 3: Triển khai hệ thống (Deploy)
Chương này hướng dẫn quy trình build và triển khai ứng dụng Java (Spring Boot) lên các môi trường dev/staging/production. Bao gồm chuẩn bị hạ tầng, build artifact (JAR), cấu hình biến môi trường, chạy ứng dụng dạng service hoặc Docker container, cấu hình reverse proxy (Nginx), database migration và kiểm tra sau triển khai. Mục tiêu đảm bảo ứng dụng chạy ổn định, có thể giám sát và rollback khi cần.
Hướng dẫn chi tiết
1. Yêu cầu hạ tầng
Server tối thiểu
-
CPU: ≥ 2 core
-
RAM: ≥ 4 GB (prod ≥ 8 GB)
-
Disk: ≥ 20 GB
-
OS: Linux (Ubuntu 20.04+ / CentOS 7+)
-
Java: OpenJDK 17 (khuyến nghị LTS)
Cài Java:
2. Build ứng dụng
Build bằng Maven
Artifact tạo ra:
Chương 4: Kiểm thử đơn vị (Unit Test)
Chương này hướng dẫn cách viết unit test cho API trong ứng dụng Java Spring Boot. Nội dung bao gồm cấu trúc test chuẩn, cách mock dependency, kiểm tra validate input, xác thực (authentication/authorization), ghi log, xử lý exception và kiểm tra logic service. Mục tiêu đảm bảo mỗi API hoạt động đúng, an toàn và ổn định trước khi tích hợp hoặc triển khai.
Nội dung chi tiết
1. Nguyên tắc Unit Test API
Mỗi API cần test các nhóm case cơ bản:
-
Validate input
-
Auth / permission
-
Business logic
-
Repository interaction
-
Exception handling
-
Logging
-
HTTP status & response
2. Ví dụ API mẫu
Controller:
DTO:
Service:
3. Cấu trúc test chuẩn
Dependency:
Controller test dùng:
-
@WebMvcTest
-
MockMvc
-
@MockBean
4. Test Validate Input
Case cần có:
-
thiếu field bắt buộc
-
email sai format
-
request null
5. Test Auth / Permission
Giả sử API cần login:
Test chưa login:
6. Test Business Logic (Service)
7. Test Exception Handling
Giả sử email trùng:
Test:
8. Test Logging
Giả sử service có log:
Test log:
(Thực tế có thể dùng LogCaptor)
9. Test HTTP Response
10. Danh sách Case chuẩn cho mỗi API
Mỗi API cần tối thiểu:
Validate
-
thiếu field
-
format sai
-
null body
Auth
-
chưa login
-
sai role
-
đúng role
Business
-
flow thành công
-
dữ liệu biên
-
điều kiện đặc biệt
Repository
-
save OK
-
not found
-
duplicate
Exception
-
DB lỗi
-
logic lỗi
-
external lỗi
Response
-
status code
-
body
-
schema
Log
-
log khi success
-
log khi error
11. Checklist Unit Test API
-
Test validate
-
Test auth
-
Test service
-
Mock repo
-
Test exception
-
Test response
-
Verify interaction
-
No DB thật
-
No network
Chương 5: Đóng gói & phát hành (Packaging)
Chương này hướng dẫn cách đóng gói dự án thành artifact phát hành (jar, docker image, bundle web…), đặt version, ghi changelog, ký số (nếu có) và lưu trữ trên repository. Kết quả là gói cài đặt sẵn sàng để triển khai hoặc phân phối.
Chương 6: Sử dụng AI agent skill
chương này hướng dẫn cách hoạt động và sử dụng AI để thực hiện các tác vụ về tạo mới api
Nội dung chi tiết
1. Cài đặt ban đầu — Clone thư mục .agent
Trước khi sử dụng skill, bạn cần clone repository cấu hình về thư mục gốc của project bằng lệnh sau:
git clone -b master http://192.168.0.95/minhnd/chat-gpt-agent.git .agent
Lệnh trên sẽ tải branch master và đặt toàn bộ nội dung vào thư mục .agent ngay trong thư mục hiện tại của bạn.
Lưu ý: Chạy lệnh này tại thư mục gốc (root) của project, không phải bên trong thư mục con nào khác.
2. Hướng dẫn cài đặt Google Antigravity Truy cập link sau https://antigravity.google/download
Sau đó cài đặt như bình thường.
3. Mục tiêu của Skill
Skill này được thiết kế để:
• Chuẩn hóa cấu trúc dự án Spring Boot.
• Đảm bảo tính nhất quán (Consistency) giữa các module.
• Tự động hóa việc ra quyết định về kiến trúc (Layered Architecture).
• Tuân thủ các quy tắc bảo mật và lưu vết (Audit log).
4. Cách kích hoạt (Activation)
Skill này hoạt động hoàn toàn TỰ ĐỘNG khi project có thư mục cấu hình .agent.
Cơ chế: Khi bạn gửi yêu cầu (ví dụ: "Tạo API User"), hệ thống nhận diện .agent, kích hoạt @backend-specialist và tự động áp dụng các quy chuẩn trong skill api-processing-flow.
Lưu ý: Bạn không cần copy nội dung skill vào chatbot, chỉ cần đảm bảo thư mục .agent nằm trong project.
5. Các Quy tắc "Vàng" (Mandatory Rules)
Cần tuân thủ 5 quy tắc bắt buộc sau khi viết code:
1. Kiến trúc 3 lớp: Luôn tuân theo luồng Controller -> Service -> Repository.
2. Không Logic ở Controller: Controller chỉ nhận request, check validation cơ bản và gọi Service.
3. ApiResponse Standard: Mọi API phải trả về object ApiResponse<T>. Không trả về trực tiếp DTO hay Entity.
4. DTO vs Entity: Tuyệt đối không trả về Entity cho Client. Luôn dùng DTO cho Request và Response.
5. In-memory Storage: Dùng ConcurrentHashMap hoặc List trong Repository nếu chưa có Database bên ngoài.
5b. Cấu trúc Module chuẩn
Mỗi module mới khi tạo ra phải có cấu trúc thư mục như sau:
modules/<module-name>/
+-- controller/ (Chua @RestController)
+-- service/ (Chua Business Logic & Interface)
+-- repository/ (Chua truy van du lieu)
+-- entity/ (Chua mapping du lieu)
+-- dto/ (Chua Request/Response models)
6. Quy trình phát triển 5 bước (API Workflow)
Để tạo một tính năng mới, hãy đi theo trình tự:
6. B1: Tạo DTO: Định nghĩa Request và Response model.
7. B2: Tạo Entity: Định nghĩa cấu trúc dữ liệu mapping.
8. B3: Tạo Repository: Định nghĩa các phương thức lưu trữ dữ liệu.
9. B4: Tạo Service: Viết Business Logic (Xử lý dữ liệu, chuyển đổi Entity <-> DTO).
10. B5: Tạo Controller: Khai báo Endpoint và gọi Service.
7. Coding Convention (Quy tắc đặt tên)
Bảng quy ước đặt tên các thành phần trong dự án:
Thành phần Quy tắc đặt tên Ví dụ
Controller <n>Controller UserController
Service <n>Service UserService
Repository <n>Repository UserRepository
Entity <n>Entity UserEntity
DTO Request <n>CreateRequest UserCreateRequest
DTO Response <n>Response UserResponse
8. Ví dụ một phương thức Service chuẩn
Dưới đây là cấu trúc chuẩn của một phương thức trong Service layer:
public UserResponse create(UserCreateRequest request) {
// 1. Validate (Kiem tra du lieu)
if (repo.existsByUsername(request.getUsername())) {
throw new BusinessException(ErrorCode.USER_EXISTS);
}
// 2. Log (Luu vet hanh dong)
log.info("Creating user: {}", request.getUsername());
// 3. Business logic (Xu ly)
UserEntity entity = mapper.toEntity(request);
repo.save(entity);
// 4. Return (Tra ve ket qua)
return mapper.toResponse(entity);
}
10. Cơ chế hoạt động
Thư mục .agent (Antigravity Kit) đóng vai trò là "bộ não" và hệ thống điều hành của trợ lý AI trong dự án. Nó chứa các định nghĩa về vai trò, kỹ năng, quy trình làm việc và các kịch bản tự động hóa đảm bảo chất lượng code.
11. Cấu trúc thư mục .agent
Cấu trúc chuẩn của thư mục .agent:
.agent/
+-- rules/
| +-- GEMINI.md # Quy tắc tối cao(P0), định nghĩa hành vi cơ bản
+-- agents/ # Danh sách 20 Agent(Personas)
+-- skills/ # Các kỹ năng mo-dun hóa (Domain knowledge)
+-- workflows/ # Quy trình làm việc (/plan, /create, /debug...)
+-- scripts/ # Các kịch bản kiểm tra và tự động hóa master
+-- ARCHITECTURE.md # Bản đồ tổng thể hế thống Agent
+-- tasks/ # Lưu trữ tài liệu và các tác vụ({task-slug}.md)
12. Luồng xử lý — Từ yêu cầu đến code
Mỗi yêu cầu gõ vào chạy qua đúng 6 cổng theo thứ tự sau. Không cổng nào bị bỏ qua:
[USER INPUT]
|
v
[1] Request Classifier <- rules/GEMINI.md doc vao dau tien
| QUESTION --> trả lời thẳng,kết thúc.
| SIMPLE CODE --> chuyển sang bước 2.
| COMPLEX --> tạo tasks/{task-slug}.md rồi mới sang bước 2.
v
[2] Agent Routing <- đọc agents/ chọn đúng agent
| ví dụ: viết API --> @backend-specialist
| viết UI --> @frontend-specialist
| kiểm tra sec --> @security-auditor
v
[3] Modular Skill Loading <- chỉ đọc skills/ cần thiết, không đọc hết
| ví dụ: @backend + API --> skills/api-patterns + nodejs-best-practices
| mọi folder Skill gồm: SKILL.md (hướng dẫn) + scripts/ (công cụ)
v
[4] Rule Priority Check <- áp dụng theo thứ tự P0 > P1 > P2
| P0: rules/GEMINI.md (Toàn cục -cao nhất, không thể override)
| P1: agents/{agent}.md (quy tắc riêng của Specialist)
| P2: skills/{skill}.md (kỹ thuật cụ thể cửa Skill được nạp)
v
[5] Socratic Gate <- chỉ áp dụng với COMPLEX CODE
| AI hỏi >= 3 câu trước khi viết bất kỳ dòng code nào:
| - Mục tiêu chính là gì?
| - Edge cases nào cần xử lý?
| - Ràng buộc kiến trúc/công nghệ?
v
[6] Implementation & Validation <- viết code + tự động kiểm tra
| Viết code: Clean Code + TDD
| scripts/checklist.py --> Bảo mật, Lint, Schema, UX (nhanh)
| scripts/verify_all.py --> E2E, Performance, SEO (truoc deploy)
v
[OUTPUT] Code đạt chuẩn, đã quan kiểm tra, sẵn sàng review.
13. Các lệnh Slash Commands phổ biến
Hệ thống hỗ trợ các quy trình chuẩn hóa thông qua lệnh /. Gõ trực tiếp trong chat để kích hoạt:
/plan — Lập kế hoạch chi tiết, chia nhỏ tác vụ (không viết code).
/create — Bắt đầu tạo một tính năng hoặc ứng dụng mới.
/debug — Kích hoạt chế độ kiểm tra lỗi hệ thống 4 giai đoạn.
/orchestrate — Phối hợp nhiều chuyên gia để giải quyết vấn đề đa chiều.
/status — Kiểm tra tiến độ và trạng thái hiện tại của dự án.
Ghi chú: Mọi thay đổi đối với cấu trúc hệ thống Agent nên được thực hiện thông qua việc cập nhật các file trong .agent để đảm bảo AI luôn cập nhật được “tư duy” mới nhất.