Giới thiệu
Xây dựng chú thích tùy chỉnh để ghi nhận thông tin yêu cầu HTTP cho các phương thức API cụ thể.
Công nghệ sử dụng
- Spring Boot 2.7+
- Spring AOP
- MySQL 8.0+
Triển khai chi tiết
1. Định nghĩa chú thích
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestLog {
String description() default "Không xác định";
ActivityType type() default ActivityType.OTHER;
boolean recordIP() default true;
boolean recordPayload() default true;
}
2. Enum loại hoạt động
public enum ActivityType {
DANG_NHAP("Đăng nhập"),
DANG_XUAT("Đăng xuất"),
TIM_KIEM("Tra cứu"),
THEM_MOI("Thêm"),
CAP_NHAT("Sửa"),
XOA("Xóa"),
KHAC("Khác");
private final String label;
ActivityType(String label) { this.label = label; }
}
3. Cấu hình AOP
@Aspect
@Component
public class RequestLogAspect {
@Autowired
private LogRepository logRepo;
@Pointcut("@annotation(com.example.demo.annotation.RequestLog)")
public void logPointcut() {}
@Around("logPointcut()")
public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RequestLog logConfig = method.getAnnotation(RequestLog.class);
if (logConfig == null) return joinPoint.proceed();
LogEntry entry = new LogEntry();
entry.setDescription(logConfig.description());
entry.setType(logConfig.type());
// Ghi thông tin yêu cầu
if (logConfig.recordIP() || logConfig.recordPayload()) {
ServletRequestAttributes attr =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attr.getRequest();
if (logConfig.recordIP()) {
entry.setIpAddress(getClientIP(request));
}
if (logConfig.recordPayload()) {
entry.setRequestData(Arrays.toString(joinPoint.getArgs()));
}
}
// Ghi thông tin người dùng
entry.setUserId(UserContext.getCurrentUser().getId());
// Lưu nhật ký
logRepo.save(entry);
return joinPoint.proceed();
}
}
4. Cấu trúc bảng cơ sở dữ liệu
CREATE TABLE system_audit_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
ip_address VARCHAR(45),
request_path VARCHAR(255),
activity_type ENUM('DANG_NHAP','DANG_XUAT','TIM_KIEM','THEM_MOI','CAP_NHAT','XOA','KHAC'),
description TEXT,
request_data TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) PARTITION BY RANGE COLUMNS(created_at) (
PARTITION p202408 VALUES LESS THAN ('2024-09-01'),
PARTITION p202409 VALUES LESS THAN ('2024-10-01')
);
5. Sử dụng chú thích
@RestController
@RequestMapping("/api/users")
public class UserController {
@RequestLog(description = "Lấy danh sách người dùng", type = ActivityType.TIM_KIEM)
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
}