Trong bối cảnh thương mại điện tử và mạng xã hội phát triển mạnh mẽ, nhu cầu về giải pháp thời trang cá nhân hóa ngày càng gia tăng. Người tiêu dùng không chỉ tìm kiếm sản phẩm phù hợp mà còn kỳ vọng vào trải nghiệm chọn lựa được hỗ trợ bởi phân tích dữ liệu và trí tuệ nhân tạo. Tuy nhiên, khối lượng lớn sản phẩm, sự đa dạng về phong cách và thiếu công cụ đánh giá khách quan khiến việc xây dựng tủ đồ tối ưu trở thành thách thức thực tế — đặc biệt với những người không có nền tảng thiết kế hoặc tư vấn thời trang chuyên nghiệp.
Các hệ thống đề xuất truyền thống thường dựa vào lịch sử hành vi (mua hàng, xem, thích) hoặc thuật toán lọc cộng đồng đơn giản, dẫn đến kết quả mang tính chung chung và ít phản ánh đặc điểm cá nhân như dáng người, tông da, sở thích thẩm mỹ hoặc ngữ cảnh sử dụng (ví dụ: công sở, dạo phố, sự kiện đặc biệt). Giải pháp hiện đại khắc phục hạn chế này bằng cách tích hợp nhiều lớp dữ liệu: đặc trưng hình ảnh từ ảnh selfie (phân tích đường nét khuôn mặt, tỷ lệ cơ thể, độ tương phản da), dữ liệu thời tiết theo vị trí, xu hướng mùa vụ từ nguồn dữ liệu thời trang mở, và mô hình hành vi dài hạn của người dùng. Kết quả là một bộ đề xuất phối đồ được sinh ra theo nguyên tắc "một lần cấu hình — nhiều kịch bản ứng dụng", nơi mỗi món đồ trong tủ đồ cá nhân có thể được tái sử dụng linh hoạt dưới các bối cảnh khác nhau.
Mặt khác, xu hướng thời trang bền vững đang thúc đẩy mô hình "tối ưu hóa tủ đồ hiện có" thay vì khuyến khích mua sắm mới. Hệ thống đề xuất thông minh có thể hoạt động như một trợ lý cá nhân số: phân tích danh mục quần áo đã có (thông qua nhập thủ công hoặc quét mã vạch/ảnh), sau đó tự động tạo ra các tổ hợp phối màu, chất liệu và phong cách phù hợp — từ đó nâng cao tỷ lệ sử dụng sản phẩm, giảm lãng phí và hỗ trợ quyết định mua sắm có chủ đích.
Về mặt kỹ thuật, hệ thống được xây dựng trên kiến trúc microservice nhẹ, với backend viết bằng Java 17, sử dụng Spring Boot 3.x để quản lý lifecycle ứng dụng, cấu hình tự động và tích hợp sẵn actuator cho giám sát hiệu năng. Cơ sở dữ liệu quan hệ MySQL 8.0 đảm bảo tính toàn vẹn dữ liệu và khả năng mở rộng khi xử lý bảng người dùng, bảng sản phẩm và bảng lịch sử đề xuất. Giao diện người dùng được triển khai dưới dạng Progressive Web App (PWA), hỗ trợ cả nền tảng di động và desktop, với khả năng lưu offline và đồng bộ khi có kết nối.
Dưới đây là đoạn mã xử lý tải lên và quản lý tài nguyên hình ảnh — được tái thiết kế nhằm tăng tính bảo mật và khả năng mở rộng:
package com.fashion.recommender.controller;
import com.fashion.recommender.exception.UploadException;
import com.fashion.recommender.model.FileMetadata;
import com.fashion.recommender.service.FileStorageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
@RestController
@RequestMapping("/api/v1/assets")
public class AssetController {
private final FileStorageService storageService;
private final String uploadRootPath;
public AssetController(FileStorageService storageService,
@Value("${app.upload-dir:./uploads}") String uploadDir) {
this.storageService = storageService;
this.uploadRootPath = uploadDir;
}
@PostMapping("/upload")
public ResponseEntity<FileMetadata> handleFileUpload(
@RequestParam("image") MultipartFile file,
@RequestParam(value = "category", required = false) String category) {
if (file.isEmpty()) {
throw new UploadException("Tệp tải lên không được để trống");
}
try {
String uniqueId = UUID.randomUUID().toString();
String storedFileName = storageService.store(file, uniqueId, category);
FileMetadata metadata = new FileMetadata();
metadata.setId(uniqueId);
metadata.setOriginalName(file.getOriginalFilename());
metadata.setStoredName(storedFileName);
metadata.setContentType(file.getContentType());
metadata.setSize(file.getSize());
return ResponseEntity.ok(metadata);
} catch (IOException e) {
throw new UploadException("Lỗi khi lưu tệp: " + e.getMessage(), e);
}
}
@GetMapping("/download/{id}")
public ResponseEntity<byte[]> downloadFile(@PathVariable String id) {
byte[] content = storageService.retrieve(id);
return ResponseEntity.ok()
.header("Content-Disposition", "attachment; filename=\"" + id + ".jpg\"")
.body(content);
}
}
Đoạn mã phía client sử dụng JavaScript thuần để điều hướng sau khi khởi tạo phiên làm việc — loại bỏ hoàn toàn phụ thuộc vào JSP và servlet container truyền thống:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hệ thống phối đồ thông minh</title>
<script>
// Chuyển hướng tự động tới giao diện quản trị sau khi xác thực
document.addEventListener('DOMContentLoaded', () => {
const token = localStorage.getItem('auth_token');
if (token && !window.location.pathname.includes('admin')) {
window.location.replace('/admin/');
} else if (!token) {
window.location.replace('/login');
}
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
Hệ thống áp dụng chiến lược kiểm thử phân cấp: kiểm thử đơn vị (unit test) cho các service xử lý đề xuất, kiểm thử tích hợp (integration test) cho luồng API ↔ database, và kiểm thử chấp nhận (acceptance test) dựa trên kịch bản người dùng thực tế (ví dụ: "Người dùng A tải ảnh selfie → hệ thống trả về 3 bộ phối cho môi trường văn phòng vào mùa hè"). Các case kiểm thử được tự động hóa bằng JUnit 5 và Testcontainers, đảm bảo khả năng tái hiện môi trường production trong CI/CD pipeline.
Về mặt kiến trúc, hệ thống phân tách rõ ràng giữa lớp trình bày (frontend PWA), lớp nghiệp vụ (Spring Boot REST API), và lớp dữ liệu (MySQL + Redis cache cho các đề xuất phổ biến). Việc không sử dụng Eclipse mà chuyển sang IntelliJ IDEA Community Edition giúp tận dụng tốt hơn các tính năng phân tích mã tĩnh và hỗ trợ Spring Boot native, đồng thời giảm thiểu rủi ro từ các plugin không kiểm chứng.