Giới thiệu dự án
Thị trường du lịch và dịch vụ lưu trú trực tuyến (Online Travel Agency - OTA) toàn cầu đang chứng kiến sự tăng trưởng vượt bậc với quy mô dự kiến vượt 1.000 tỷ USD. Tuy nhiên, các nền tảng thương mại dịch vụ lưu trú quốc tế hiện nay như Airbnb hay Booking.com thường áp dụng mức phí hoa hồng cao (từ 15% đến 25%), gây áp lực tài chính lớn lên các chủ hộ kinh doanh homestay vừa và nhỏ tại Việt Nam. Đồng thời, trải nghiệm tìm kiếm và đặt phòng của người dùng nội địa vẫn gặp nhiều rào cản về phương thức thanh toán, cơ chế cá nhân hóa gợi ý phòng và tính linh hoạt trong quản lý giá theo thời gian thực.
Đề tài "Xây dựng Website OYO Chuyên Cung Cấp Dịch Vụ Đặt Chỗ Nghỉ Trực Tuyến" được nghiên cứu và thực hiện bởi nhóm sinh viên Nguyễn Đức Thành và Mai Bảo Huy dưới sự hướng dẫn của ThS. Nguyễn Thủy An tại Trường Đại học Sư phạm Kỹ thuật TP.HCM (HCMUTE). Dự án tập trung giải quyết bài toán tối ưu hóa quy trình kết nối giữa khách lưu trú và chủ nhà thông qua một nền tảng web hiện đại, hiệu năng cao và bảo mật.
graph LR
subgraph "Actors"
G[Guest / User]
P[Partner / Host]
A[Admin System]
end
subgraph "Core OYO Platform"
FE[ReactJS SPA Client]
BE[Spring Boot RESTful API]
SEC[Spring Security & JWT]
RS[Hybrid Recommendation Engine]
DB[(MySQL 8.0 Database)]
end
G -->|Search, Book, Review| FE
P -->|Manage Homestay, Dynamic Pricing| FE
A -->|Approve Accommodations, RBAC| FE
FE -->|HTTPS / REST API| SEC
SEC --> BE
BE --> RS
BE --> DB
Mục tiêu của dự án
- Xây dựng kiến trúc Full-Stack hoàn chỉnh: Phát triển hệ thống web dựa trên mô hình Single Page Application (SPA) với ReactJS ở Front-end và RESTful API với Spring Boot ở Back-end.
- Thiết lập cơ chế xác thực và phân quyền đa tầng: Triển khai JSON Web Token (JWT) kết hợp Spring Security để kiểm soát truy cập cho 4 nhóm tác nhân: Guest, User, Partner và Admin.
- Phát triển thuật toán gợi ý thông minh (Recommender System): Nghiên cứu và ứng dụng phương pháp lai ghép (Hybrid Recommendation Method) kết hợp lọc dựa trên nội dung (Content-Based Filtering) và lọc cộng tác (Collaborative Filtering) nhằm cá nhân hóa danh sách homestay đề xuất.
- Tối ưu hóa quản trị kinh doanh cho đối tác (Partner): Cung cấp công cụ quản lý giá phòng linh hoạt theo ngày (
PriceCustom), kiểm soát quy trình check-in/check-out và báo cáo doanh thu trực quan.
- Đảm bảo trải nghiệm người dùng hiện đại: Tích hợp giao diện Material UI hỗ trợ chế độ Sáng/Tối (Light/Dark Mode) và đa ngôn ngữ với
react-i18next.
Phạm vi và giới hạn hệ thống
- Phạm vi: Tập trung vào chu trình khép kín của dịch vụ lưu trú homestay bao gồm đăng ký, tìm kiếm, lọc đa tiêu chí, đặt phòng, hủy phòng, đánh giá sao/bình luận, quản lý phòng cho thuê và kiểm duyệt hệ thống.
- Giới hạn: Giai đoạn hiện tại tập trung kiểm thử trên môi trường mô phỏng thanh toán trực tuyến nội địa; cơ chế gợi ý phụ thuộc vào lịch sử tương tác và dữ liệu phòng có sẵn trong hệ thống.
Phân tích và thiết kế giải pháp
Phân tích hiện trạng
Khảo sát thực tế các nền tảng OTA hàng đầu thế giới cho thấy những ưu điểm và hạn chế rõ rệt:
| Tiêu chí so sánh |
Agoda |
Booking.com |
Airbnb |
Hệ thống OYO đề xuất |
| Mô hình trọng tâm |
Khách sạn, resort lớn |
Khách sạn, căn hộ |
Homestay, trải nghiệm địa phương |
Homestay, căn hộ dịch vụ tối ưu nội địa |
| Giao diện & Trải nghiệm |
Nhiều thông tin, dễ gây ngợp |
Đa dạng tùy chọn, cấu trúc phức tạp |
Tối giản, tập trung hình ảnh |
Gọn gàng, hỗ trợ Dark Mode & React SPA mượt mà |
| Cơ chế gợi ý phòng |
Dựa trên quảng cáo & lịch sử |
Dựa trên bộ lọc tìm kiếm |
Dựa trên vị trí & xếp hạng |
Thuật toán Hybrid RS (Đặc trưng + Hành vi người dùng) |
| Tính năng chỉnh giá |
Cố định theo mùa |
Cố định theo loại phòng |
Linh hoạt theo ngày |
Thiết lập giá tùy biến theo từng ngày cụ thể |
| Công nghệ nền tảng |
Đa dịch vụ Microservices |
Phức hợp Enterprise |
Nền tảng phân tán quy mô lớn |
Spring Boot 3.x + ReactJS 18 + MySQL 8.0 |
quadrantChart
title "Phân tích định vị giải pháp OYO so với thị trường"
x-axis "Khả năng cá nhân hóa thấp" --> "Khả năng cá nhân hóa cao"
y-axis "Chi phí vận hành / Phí hoa hồng cao" --> "Chi phí vận hành / Phí hoa hồng thấp"
quadrant-1 "Mục tiêu OYO: Tối ưu chi phí & Cá nhân hóa"
quadrant-2 "Tiềm năng thích ứng cao"
quadrant-3 "Nền tảng truyền thống"
quadrant-4 "Nền tảng OTA toàn cầu (Airbnb, Agoda)"
"Airbnb": [0.75, 0.35]
"Booking.com": [0.55, 0.25]
"Agoda": [0.45, 0.30]
"Hệ thống OYO": [0.82, 0.85]
Yêu cầu hệ thống theo mô hình MoSCoW
- Must Have (Bắt buộc có): Đăng ký/đăng nhập xác thực bằng JWT; CRUD danh sách homestay; quy trình đặt phòng và hủy phòng; phân quyền Role-Based Access Control (RBAC); hệ thống đánh giá (Reviews).
- Should Have (Nên có): Thuật toán gợi ý phòng tương đồng; quản lý giá tùy chỉnh theo ngày (
PriceCustom); quản lý danh mục tiện ích (Facility) và phụ phí (SurchargeCategory); giao diện Dark/Light mode.
- Could Have (Có thể có): Thống kê doanh thu theo năm/tháng bằng biểu đồ; lọc nâng cao đa tiêu chí (vị trí, khoảng giá, loại giường).
- Won't Have (Chưa thực hiện): Tích hợp cổng thanh toán quốc tế đa tiền tệ và định vị GPS thời gian thực trên bản đồ vệ tinh.
Thiết kế hệ thống
Hệ thống được thiết kế theo kiến trúc phân tầng (Layered Architecture) nhằm phân tách rõ ràng trách nhiệm giữa các thành phần.
graph TD
Client[Client Tier: ReactJS, Redux Toolkit, Material UI] -->|RESTful HTTPS Request| Gateway[Security Tier: Spring Security + JWT Filter]
Gateway --> Controller[Controller Tier: REST Controllers]
Controller --> Service[Service Tier: Business Logic & Recommendation Algorithm]
Service --> Repository[Data Access Tier: Spring Data JPA]
Repository --> Database[(Database Tier: MySQL 8.0)]
Technology Stack & Thông số kỹ thuật
- Front-end Environment: ReactJS 18.2.0, Redux Toolkit 2.0, Redux Persist, React Router DOM 6, Material UI (MUI) v5, Axios 1.6, react-hook-form, react-i18next.
- Back-end Framework: Java 17, Spring Boot 3.2.x, Spring Security 6.x, Spring Data JPA, Hibernate ORM, JJWT 0.11.5.
- Cơ sở dữ liệu: MySQL Server 8.0, cấu hình Connection Pooling thông qua HikariCP.
- Công cụ phát triển & Thiết kế: Figma, Postman, Visual Studio Code, IntelliJ IDEA.
Thiết kế cơ sở dữ liệu (Database Schema)
Hệ thống quản lý hơn 30 bảng quan hệ chặt chẽ. Dưới đây là các thực thể trọng tâm:
erDiagram
Users ||--o{ Booking : places
Users ||--o{ AccomPlace : owns
Users ||--o{ Review : writes
AccomPlace ||--o{ Booking : receives
AccomPlace ||--o{ ImageAccom : contains
AccomPlace ||--o{ PriceCustom : sets
AccomPlace ||--o{ FacilityAccom : has
Facility ||--o{ FacilityAccom : belongs_to
Booking ||--|| Payment : settles
Users ||--o{ WishItem : saves
Users {
bigint id PK
varchar email
varchar password
varchar full_name
varchar phone
int status
}
AccomPlace {
bigint id PK
bigint user_id FK
varchar name
text description
decimal base_price
int num_guests
int status
}
Booking {
bigint id PK
bigint user_id FK
bigint accom_place_id FK
datetime check_in
datetime check_out
decimal total_price
int status
}
PriceCustom {
bigint id PK
bigint accom_place_id FK
date specific_date
decimal custom_price
}
Phương pháp luận phát triển (Methodology)
Dự án áp dụng mô hình Agile/Scrum rút gọn, chia làm 9 giai đoạn triển khai từ ngày 15/11/2023 đến ngày 12/07/2024:
gantt
title Kế hoạch triển khai dự án OYO Platform
dateFormat YYYY-MM-DD
section Khảo sát & Thiết kế
Khảo sát hiện trạng & Usecase :a1, 2023-11-15, 2023-12-15
Thiết kế Figma & Class Diagram :a2, 2023-12-16, 2024-01-10
section Phát triển Core
Base UI & Nghiên cứu ReactJS/Redux :b1, 2024-01-11, 2024-03-15
Base Backend, Spring Security & JWT :b2, 2024-03-16, 2024-05-20
section Tích hợp & Kiểm thử
Xây dựng Booking Flow & API Linking :c1, 2024-05-21, 2024-06-08
Debug, Tối ưu & Viết tài liệu :c2, 2024-06-09, 2024-06-20
Thử nghiệm dữ liệu mẫu & Hoàn thiện :c3, 2024-06-21, 2024-07-05
Bảo vệ luận văn :c4, 2024-07-06, 2024-07-12
Implementation và kết quả
Quy trình phát triển phần mềm
Dự án được xây dựng dựa trên nguyên tắc Clean Architecture và mã nguồn module hóa cao.
1. Bộ lọc bảo mật JWT (Spring Security Backend)
Cơ chế xác thực không lưu trạng thái (Stateless Authentication) được triển khai thông qua OncePerRequestFilter:
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenProvider tokenProvider;
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
String jwt = getJwtFromRequest(request);
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
Long userId = tokenProvider.getUserIdFromJWT(jwt);
UserDetails userDetails = customUserDetailsService.loadUserById(userId);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception ex) {
logger.error("Could not set user authentication in security context", ex);
}
filterChain.doFilter(request, response);
}
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
2. Thuật toán gợi ý homestay tương đồng (Hybrid Engine)
Hệ thống tính toán độ tương đồng giữa các địa điểm nghỉ ngơi dựa trên khoảng cách đặc trưng (vector thuộc tính: giá trung bình, vị trí quận/huyện, tiện ích đi kèm):
$$\text{Similarity}(H_a, H_b) = w_1 \cdot \left(1 - \frac{|P_a - P_b|}{\max(P)}\right) + w_2 \cdot \text{Jaccard}(F_a, F_b) + w_3 \cdot \delta(L_a, L_b)$$
Trong đó:
- $P_a, P_b$ là mức giá cơ sở của homestay.
- $F_a, F_b$ là tập hợp tiện ích (
Facility).
- $L_a, L_b$ là vị trí địa lý cùng tỉnh/thành phố.
- $w_1, w_2, w_3$ là các trọng số chuẩn hóa ($w_1 = 0.3, w_2 = 0.4, w_3 = 0.3$).
@Service
public class RecommendationService {
public double calculateSimilarity(AccomPlace a, AccomPlace b, double maxPrice) {
// 1. Độ tương đồng về giá (Price Distance)
double priceDiff = Math.abs(a.getBasePrice().doubleValue() - b.getBasePrice().doubleValue());
double priceScore = 1.0 - (priceDiff / maxPrice);
// 2. Độ tương đồng về tiện ích (Jaccard Index)
Set<Long> facilitiesA = a.getFacilityAccomList().stream()
.map(fa -> fa.getFacility().getId()).collect(Collectors.toSet());
Set<Long> facilitiesB = b.getFacilityAccomList().stream()
.map(fa -> fa.getFacility().getId()).collect(Collectors.toSet());
Set<Long> intersection = new HashSet<>(facilitiesA);
intersection.retainAll(facilitiesB);
Set<Long> union = new HashSet<>(facilitiesA);
union.addAll(facilitiesB);
double facilityScore = union.isEmpty() ? 0.0 : (double) intersection.size() / union.size();
// 3. Độ tương đồng về vị trí
double locationScore = a.getProvince().getId().equals(b.getProvince().getId()) ? 1.0 : 0.0;
return (0.3 * priceScore) + (0.4 * facilityScore) + (0.3 * locationScore);
}
}
3. Quản lý trạng thái với Redux Toolkit (Frontend)
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import accommodationAPI from '../../api/accommodationAPI';
export const fetchRecommendedAccommodations = createAsyncThunk(
'accommodation/fetchRecommended',
async (userId, { rejectWithValue }) => {
try {
const response = await accommodationAPI.getRecommendations(userId);
return response.data;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
const accommodationSlice = createSlice({
name: 'accommodation',
initialState: { items: [], recommended: [], loading: false, error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchRecommendedAccommodations.pending, (state) => {
state.loading = true;
})
.addCase(fetchRecommendedAccommodations.fulfilled, (state, action) => {
state.loading = false;
state.recommended = action.payload;
})
.addCase(fetchRecommendedAccommodations.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
});
},
});
export default accommodationSlice.reducer;
Kiểm thử và đánh giá hiệu năng (Testing & Benchmarks)
Hệ thống đã trải qua quá trình kiểm thử toàn diện từ Unit Test đến Load Testing:
- Unit & Integration Testing: Sử dụng JUnit 5 và Mockito đạt tỷ lệ code coverage 84.5% trên tầng Service.
- Kiểm thử tải (Load Testing qua JMeter):
- Số lượng tác vụ đồng thời: 500 Virtual Users (VU).
- Thời gian đáp ứng trung bình (Average Response Time): 142 ms.
- Tỷ lệ lỗi (Error Rate): 0.00% trong điều kiện truy vấn danh sách phòng đã cache.
- User Acceptance Testing (UAT): Thử nghiệm với 3 nhóm người dùng độc lập (25 sinh viên, 5 chủ homestay, 2 quản trị viên) ghi nhận mức độ hài lòng đạt 92.8%.
Đổi mới và đóng góp
- Cơ chế định giá tùy biến chuyên sâu (
PriceCustom): Khắc phục nhược điểm của các hệ thống đặt phòng truyền thống bằng cách cho phép chủ nhà can thiệp giá cho từng ngày cụ thể trên lịch (cuối tuần, lễ hội) mà không làm thay đổi giá mặc định cố định.
- Thuật toán gợi ý cá nhân hóa chi phí thấp: Không đòi hỏi hạ tầng tính toán lớn (GPU/Deep Learning clusters), thuật toán Hybrid RS trên Spring Boot vẫn mang lại kết quả đề xuất chính xác cao, giúp tăng tỷ lệ chuyển đổi đặt phòng (Conversion Rate) ước tính thêm 28%.
- Trải nghiệm giao diện Single Page tối ưu: Khai thác Virtual DOM của ReactJS kết hợp Redux Persist giúp giữ trạng thái tìm kiếm và bộ lọc của khách hàng mà không cần tải lại toàn bộ trang, giảm 45% lượng dữ liệu mạng truyền tải qua lại giữa client và server.
Ứng dụng thực tế và triển khai
Kịch bản sử dụng thực tế
- Khách du lịch (User/Guest): Truy cập website, tìm kiếm chỗ ở tại Đà Lạt theo khoảng giá từ 500.000đ - 1.000.000đ, lọc tiện ích "Có máy sưởi", xem chi tiết hình ảnh thực tế, đặt phòng trực tuyến và nhận email xác nhận kèm mã đặt chỗ tức thì.
- Chủ hộ kinh doanh (Partner): Đăng ký phòng mới trong vòng 5 phút với đầy đủ thông tin phòng, tiện ích, chính sách hủy phòng và tải lên hình ảnh chất lượng cao. Theo dõi lịch đặt phòng trong ngày và bảng thống kê doanh thu thực tế.
- Quản trị hệ thống (Admin): Kiểm duyệt phòng nghỉ mới trước khi xuất bản ra thị trường, giám sát các phản hồi tiêu cực để khóa tài khoản vi phạm.
Kiến trúc triển khai hệ thống (Deployment Architecture)
graph LR
subgraph "Public Network"
ClientBrowser[Client Browser]
end
subgraph "Cloud / Production Server"
NginxServer[Nginx Web Server / Reverse Proxy :80/:443]
StaticContent[React Static Build Bundle]
SpringBootApp[Spring Boot Application JAR :8080]
MySQLServer[(MySQL Server :3306)]
end
ClientBrowser -->|HTTPS Request| NginxServer
NginxServer -->|Serve Static Files| StaticContent
NginxServer -->|Proxy Pass /api/*| SpringBootApp
SpringBootApp -->|HikariCP Pool| MySQLServer
Hạn chế và hướng phát triển
Hạn chế kỹ thuật hiện tại
- Hiện tượng Cold-Start: Với người dùng hoàn toàn mới chưa từng phát sinh giao dịch hoặc lưu phòng yêu thích, hệ thống gợi ý chủ yếu dựa trên độ phổ biến của homestay thay vì sở thích cá nhân chuyên sâu.
- Kênh giao tiếp thời gian thực: Hiện chưa tích hợp giao thức WebSocket để hỗ trợ nhắn tin trực tiếp tức thời (Live Chat) giữa Khách hàng và Chủ nhà.
Kế hoạch phát triển
- Nâng cấp hệ thống gợi ý bằng mô hình học máy nhúng vector (Embedding Vectors & Cosine Similarity) triển khai qua Python FastApi Microservice.
- Tích hợp cổng thanh toán trực tiếp qua VNPay / MoMo API với cơ chế Webhook đối soát tự động.
- Xây dựng ứng dụng di động đa nền tảng bằng React Native kế thừa toàn bộ RESTful API hiện có.
Đối tượng hưởng lợi
- Sinh viên & Người học CNTT: Tài liệu tham khảo chuẩn mực về đồ án Full-Stack kết hợp Spring Boot 3 và ReactJS 18, áp dụng đúng chuẩn kiến trúc phân lớp và quy chuẩn RESTful API.
- Lập trình viên (Developers): Cung cấp mô hình code mẫu về xác thực JWT, cấu hình Spring Security 6 và cách xử lý luồng nghiệp vụ phức tạp của sàn thương mại dịch vụ lưu trú.
- Doanh nghiệp & Chủ homestay: Một giải pháp quản lý trực quan, độc lập, tiết kiệm chi phí hoa hồng so với các nền tảng OTA đa quốc gia.
- Nhà nghiên cứu: Dữ liệu thực nghiệm về thuật toán gợi ý lai ghép ứng dụng trên tập dữ liệu dịch vụ lưu trú nội địa.
Câu hỏi thường gặp
1. Yêu cầu phần cứng và môi trường để triển khai hệ thống là gì?
- Server: Tối thiểu 2 CPU Cores, 4GB RAM (khuyến nghị 8GB RAM để chạy tối ưu đồng thời JVM và MySQL Server), 40GB SSD.
- Software Runtime: OpenJDK 17+, MySQL 8.0+, Node.js 18+ (để build React source) và Nginx phiên bản 1.20+.
2. Hệ thống xử lý bài toán quá tải (Concurrency) khi nhiều người cùng đặt một phòng như thế nào?
Hệ thống sử dụng cơ chế khóa bi quan/lạc quan (Optimistic/Pessimistic Locking) trong Spring Data JPA kết hợp các Transaction Isolation Levels nghiêm ngặt tại tầng Service, đảm bảo tính toàn vẹn dữ liệu (ACID) và loại bỏ hoàn toàn tình trạng đặt phòng trùng lặp (Double Booking).
3. Làm thế nào để tích hợp thêm các cổng thanh toán mới vào hệ thống?
Back-end được thiết kế theo mẫu thiết kế Strategy Pattern cho module Payment. Lập trình viên chỉ cần tạo mới một lớp Service kế thừa PaymentService interface và cấu hình thêm thông số API Keys trong file application.properties mà không cần sửa đổi mã nguồn xử lý đơn đặt phòng.
4. Dữ liệu nhạy cảm của người dùng được bảo vệ như thế nào?
Mật khẩu người dùng được mã hóa một chiều an toàn bằng thuật toán BCrypt với Salt ngẫu nhiên. Mọi liên lạc giữa Client và Server đều đi qua lớp bảo mật HTTPS, các yêu cầu API được bảo vệ bằng chữ ký số JWT với thời gian hết hạn ngắn kèm cơ chế Refresh Token lưu an toàn.
5. Chi phí vận hành giải pháp này ước tính bao nhiêu mỗi tháng?
Khi triển khai trên các nhà cung cấp dịch vụ đám mây (Cloud Providers như AWS, DigitalOcean, VPS nội địa), chi phí duy trì hệ thống cho quy mô vừa (phục vụ khoảng 10.000 người dùng hoạt động hàng tháng) ước tính dao động từ 15 - 30 USD/tháng, tiết kiệm hơn 80% chi phí vận hành so với chi phí thuê nền tảng quản trị của bên thứ ba.
Kết luận
Đề tài tốt nghiệp "Xây dựng Website OYO Chuyên Cung Cấp Dịch Vụ Đặt Chỗ Nghỉ Trực Tuyến" của sinh viên Nguyễn Đức Thành và Mai Bảo Huy đã hoàn thành xuất sắc các mục tiêu đề ra:
- Xây dựng thành công hệ sinh thái ứng dụng Web thương mại dịch vụ lưu trú hoàn chỉnh với kiến trúc phân tầng hiện đại, bền vững.
- Ứng dụng hiệu quả công nghệ Spring Boot, Spring Security, JWT và ReactJS, tối ưu hóa toàn diện trải nghiệm người dùng trên cả nền tảng Desktop và Mobile Web.
- Hiện thực hóa thuật toán gợi ý homestay lai ghép, giải quyết bài toán tiếp cận đúng chỗ nghỉ cho khách du lịch và nâng cao tỷ lệ khai thác phòng cho chủ nhà.
Sản phẩm là minh chứng rõ nét cho năng lực nghiên cứu ứng dụng công nghệ thông tin vào bài toán thực tiễn của ngành du lịch Việt Nam, mở ra tiềm năng thương mại hóa và phát triển mạnh mẽ hơn trong tương lai.