Dự án gồm nhiều microservice Spring Boot đặt sau Spring Cloud Gateway, đăng ký với Netflix Eureka. Client chỉ cần gọi một base URL (/api/v1/... trên cổng 8888); gateway định tuyến tới đúng service. Identity cấp token JWT (HS512); các resource server xác thực cùng khóa ký (SIGNER_KEY).
| Lĩnh vực | Lựa chọn |
|---|---|
| Ngôn ngữ & runtime | Java 22, Maven |
| Nền tảng | Spring Boot 3.x, Spring Cloud (Gateway, Eureka, OpenFeign) |
| Bảo mật | OAuth2 Resource Server, JWT HS512 dùng chung qua SIGNER_KEY |
| Dữ liệu | Mặc định JPA/H2; có driver MySQL cho cấu hình production |
| Cache | Redis + Spring Cache — hồ sơ user, chi tiết campaign & organization, chi tiết product-auction (xem phần chi tiết service) |
| Messaging | RabbitMQ — đặt giá & kết thúc đấu giá sản phẩm |
| Tích hợp | PayOS (thanh toán), Cloudinary (upload file) |
| Triển khai | Docker / Docker Compose |
| Service | Port | Vai trò |
|---|---|---|
| discovery-service | 8761 | Eureka — service registry |
| gateway-service | 8888 | Điểm vào duy nhất: route /api/v1/..., filter StripPrefix=2 |
| identity-service | 8080 | Đăng ký, đăng nhập, refresh token; phát JWT (context /identity) |
| user-service | 8081 | Hồ sơ user; cache Redis userProfiles theo userId |
| payment-service | 8082 | Tích hợp PayOS (context /payment) |
| campaign-service | 8083 | Chiến dịch, tổ chức, bình luận; cache Redis cho API đọc chi tiết |
| file-service | 8084 | Upload ảnh (Cloudinary qua biến môi trường) |
| product-service | 8085 | Đấu giá sản phẩm, bid qua RabbitMQ; Redis cho trạng thái đấu giá + cache response |
| chatbot-service | 8087 | API chat HTTP (stub; xem mục Spring AI) |
- Routes (tiền tố
${app.api-prefix}=/api/v1):identity,users/user-profiles,campaigns/organizations,product-auctions,payment,images,chat/chat-with-image. - Filter:
StripPrefix=2bỏ hai segmentapivàv1trước khi forward tới từng service.
- API xác thực dưới
/identity/...(ví dụ sau gateway:/api/v1/identity/auth/...→ service/identity/auth/...). - Dùng chung
SIGNER_KEYvới các resource server.
- Tạo hồ sơ mặc định qua Feign từ identity khi đăng ký.
- Cache:
@CacheableuserProfileschogetProfileByUserId;@CacheEvictkhi cập nhật hồ sơ.
- Chiến dịch và tổ chức; GET công khai trên
/campaigns/**và/organizations/**. - Cache (Redis):
campaignstheo id chiến dịch chogetCampaign; xóa cache khi update/delete campaign, tạo/xóa comment.organizationstheo id tổ chức chogetOrganization; xóa cache khi admin update/delete. TTL mặc định 30 phút (cấu hình Spring Cache + Redis).
- Đấu giá, xử lý bid qua consumer RabbitMQ, PayOS qua Feign tới payment-service.
- Redis: cache trạng thái đấu giá (auction state) để validate bid; response cache
productAuctionschogetAuction— xóa khi bid thành công, khi kích hoạt auction pending, hoặc khi finalize xong.
- PayOS checkout / webhook (cấu hình env theo môi trường triển khai).
- Endpoint upload; thông tin Cloudinary qua biến môi trường.
- Endpoint chat REST; hiện là stub, trả nội dung placeholder.
Client chỉ nên dùng base URL của gateway:
- Base:
http://localhost:8888/api/v1 - Ví dụ:
POST .../identity/auth/tokenGET .../campaigns?page=1&size=10GET .../product-auctions?page=1&size=10GET .../user-profiles/{userId}
Gọi thẳng cổng từng service chủ yếu để debug hoặc gọi nội bộ (ví dụ Eureka lb://).
Mặc định ChatServiceImpl trong chatbot-service là stub. Để tích hợp Spring AI:
- Thêm Spring AI BOM và starter (ví dụ OpenAI) vào
chatbot-service/pom.xml, khớp phiên bản Spring Boot của project. - Cấu hình API key / model id qua biến môi trường hoặc
application.yml(ví dụSPRING_AI_OPENAI_API_KEY). - Inject bean
ChatClient(hoặcChatModel) và gọi từChatServiceImplthay cho stub; mapChatRequest.message()sang input model. - Tuỳ chọn: thêm conversation memory (JDBC, Redis, hoặc in-memory) nếu cần hội thoại nhiều lượt.
- Build lại chatbot-service; gateway đã route
/api/v1/chatvà/api/v1/chat-with-imagetới service này.
Không cần đổi gateway trừ khi thêm path mới.
Từ thư mục gốc repo:
docker compose build
docker compose up -dCompose khởi chạy Redis, RabbitMQ, Eureka và các service có Dockerfile. Đặt SIGNER_KEY thống nhất cho identity, user, campaign, product (và mọi service dùng JWT tương tự).
- campaign-service, user-service, product-service cần
REDIS_HOST(Compose gánredis). - product-service cần
RABBITMQ_HOST(trong Compose làrabbitmq).
Mặc định H2 in-memory sẽ mất dữ liệu khi container restart; với môi trường lâu dài có thể trỏ MySQL/Postgres trong application.yml.
Cần JDK 22 và Maven:
mvn -f campaign-service/pom.xml -DskipTests packagecampaign-service chạy Spotless ở phase compile; build Docker có thể thêm -Dspotless.check.skip=true nếu cần.
Các API danh sách dùng ApiResponse<PageResponse<T>> với tham số page (mặc định 1) và size (mặc định 10).
