Stack công nghệ
Backend với Spring Boot
Spring Boot cung cấp máy chủ embedded như Tomcat, Jetty, Undertow giúp triển khai ứng dụng không cần cấu hình bên ngoài. Tính năng nổi bật là tự động cấu hình dựa trên dependencies, tích hợp sẵn các module như Spring Data, Spring Security, Spring Cloud. Giúp giảm thiểu thời gian thiết lập và mở rộng hệ thống.
Frontend với Vue.js
Vue.js sử dụng công nghệ DOM ảo để tối ưu thao tác DOM, kết hợp với binding dữ liệu hai chiều và kiến trúc component. Khi dữ liệu thay đổi, giao diện tự động cập nhật, giúp tập trung vào xử lý logic thay vì thao tác DOM thủ công.
ORM với MyBatis Plus
MyBatis Plus là công cụ mở rộng của MyBatis, hỗ trợ tự động sinh code (entity, mapper), tối ưu truy vấn phân trang, truy vấn động, khóa phiên bản. Giảm lượng code SQL thủ công và tăng tốc độ phát triển lớp truy xuất dữ liệu.
Quy trình kiểm thử hệ thống
Mục tiêu kiểm thử
Đảm bảo tính ổn định và đúng yêu cầu chức năng, phát hiện lỗi thông qua kiểm thử chức năng và kiểm thử giao diện người dùng. Tập trung vào trải nghiệm người dùng và tính toàn vẹn dữ liệu.
Kiểm thử chức năng
Mô-đun đăng nhập:
| Dữ liệu đầu vào | Kết quả mong đợi | Kết quả thực tế | Nhận xét |
|---|---|---|---|
| Tài khoản: admin | Mật khẩu: 123456 | Mã xác thực: chính xác | Đăng nhập thành công | Chuyển hướng dashboard | Kết quả khớp |
| Tài khoản: admin | Mật khẩu: sai | Mã xác thực: chính xác | Báo lỗi mật khẩu | Thông báo: Mật khẩu không đúng | Kết quả khớp |
Quản lý người dùng:
| Dữ liệu đầu vào | Kết quả mong đợi | Kết quả thực tế | Nhận xét |
|---|---|---|---|
| Nhập đầy đủ thông tin | Thêm mới thành công | Hiển thị trên danh sách | Kết quả khớp |
| Chưa nhập tên người dùng | Báo lỗi bắt buộc | Thông báo: Tên người dùng không được để trống | Kết quả khớp |
Mã nguồn minh họa
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private UserService nguoiDungService;
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> xacThuc(
@RequestParam String tenDangNhap,
@RequestParam String matKhau) {
UsersEntity user = nguoiDungService.findByUsername(tenDangNhap);
if (user == null || !user.getPassword().equals(matKhau)) {
return ResponseEntity.status(401).body(Map.of("error", "Sai thông tin đăng nhập"));
}
String token = TokenGenerator.createToken(user.getId(), user.getRole());
return ResponseEntity.ok(Map.of("token", token));
}
}
public class TokenGenerator {
public static String createToken(Long userId, String role) {
String randomKey = UUID.randomUUID().toString().replace("-", "").substring(0, 32);
Calendar expiration = Calendar.getInstance();
expiration.add(Calendar.HOUR, 2);
TokenEntity token = new TokenEntity();
token.setUserId(userId);
token.setRole(role);
token.setValue(randomKey);
token.setExpiry(expiration.getTime());
tokenRepository.save(token);
return randomKey;
}
}
Cấu trúc cơ sở dữ liệu
CREATE TABLE `token` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`userId` BIGINT NOT NULL,
`username` VARCHAR(100) NOT NULL,
`role` VARCHAR(50),
`value` VARCHAR(200) NOT NULL,
`expiry` TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `token` VALUES
(1, 1001, 'admin', 'ADMIN', 'abc123xyz', '2023-12-31 23:59:59'),
(2, 1002, 'user1', 'USER', 'def456uvw', '2023-12-31 22:00:00');