自动创建和管理日志表:
每月自动生成新的日志表,并删除六个月前的旧日志表
日志记录:
通过切面记录方法执行前、执行后和异常时的日志,并将日志信息插入到当前月份的日志表中。
日志查询:
提供按日期范围查询日志的功能,支持跨月查询并汇总结果。
// 自动生成和管理日志表
@Service
public class LogTableManager {
private final DataSource dataSource;
public LogTableManager(DataSource dataSource) {
this.dataSource = dataSource;
}
@Scheduled(cron = "0 0 0 1 * ?") // 每月1号0点执行
public void createMonthlyLogTable() {
String month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_MM"));
String tableName = "logs_" + month;
String createTableSQL = String.format(
"CREATE TABLE IF NOT EXISTS %s (" +
"id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
"timestamp TIMESTAMP NOT NULL, " +
"log_message TEXT, " +
"user_id BIGINT, " +
"details JSON)", tableName
);
executeUpdate(createTableSQL);
}
@Scheduled(cron = "0 0 0 1 * ?") // 每月1号0点执行(根据需要调整)
public void deleteOldLogTables() {
LocalDate sixMonthsAgo = LocalDate.now().minusMonths(6);
String pattern = "yyyy_MM";
String oldTableNamePrefix = "logs_";
for (LocalDate date = sixMonthsAgo.withDayOfMonth(1); date.isBefore(LocalDate.now()); date = date.plusMonths(1)) {
String month = date.format(DateTimeFormatter.ofPattern(pattern));
String tableName = oldTableNamePrefix + month;
String dropTableSQL = "DROP TABLE IF EXISTS " + tableName;
executeUpdate(dropTableSQL);
}
}
private void executeUpdate(String sql) {
CompletableFuture.runAsync(() -> {
try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement()) {
stmt.executeUpdate(sql);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
// 日志服务
@Service
public class LogService {
private final DataSource dataSource;
public LogService(DataSource dataSource) {
this.dataSource = dataSource;
}
public List<LogEntry> getLogsByDateRange(LocalDate startDate, LocalDate endDate) {
List<LogEntry> logs = new ArrayList<>();
String startMonth = startDate.format(DateTimeFormatter.ofPattern("yyyy_MM"));
String endMonth = endDate.format(DateTimeFormatter.ofPattern("yyyy_MM"));
LocalDate date = startDate;
while (date.isBefore(endDate)) {
String tableName = "logs_" + date.format(DateTimeFormatter.ofPattern("yyyy_MM"));
String sql = String.format("SELECT * FROM %s WHERE timestamp BETWEEN ? AND ?", tableName);
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setTimestamp(1, java.sql.Timestamp.valueOf(startDate.atStartOfDay()));
stmt.setTimestamp(2, java.sql.Timestamp.valueOf(endDate.atStartOfDay()));
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
LogEntry entry = new LogEntry();
entry.setId(rs.getLong("id"));
entry.setTimestamp(rs.getTimestamp("timestamp").toLocalDateTime());
entry.setLogMessage(rs.getString("log_message"));
entry.setUserId(rs.getLong("user_id"));
entry.setDetails(rs.getString("details"));
logs.add(entry);
}
}
} catch (Exception e) {
e.printStackTrace();
}
date = date.plusMonths(1);
}
return logs;
}
}
// 日志记录切面
@Aspect
@Component
public class LoggingAspect {
@Autowired
private DataSource dataSource;
@Before("execution(* com.example..*(..))") // 指定需要记录日志的切点
public void logBefore(JoinPoint joinPoint) {
log("Before method: " + joinPoint.getSignature().toShortString());
}
@AfterReturning(pointcut = "execution(* com.example..*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
log("After method: " + joinPoint.getSignature().toShortString() + " with result: " + result);
}
@AfterThrowing(pointcut = "execution(* com.example..*(..))", throwing = "exception")
public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
log("Method: " + joinPoint.getSignature().toShortString() + " threw exception: " + exception);
}
private void log(String message) {
String tableName = "logs_" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_MM"));
String sql = String.format(
"INSERT INTO %s (timestamp, log_message) VALUES (?, ?)", tableName
);
CompletableFuture.runAsync(() -> {
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setTimestamp(1, java.sql.Timestamp.valueOf(LocalDateTime.now()));
stmt.setString(2, message);
stmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
// 日志条目数据结构
public class LogEntry {
private Long id;
private LocalDateTime timestamp;
private String logMessage;
private Long userId;
private String details;
// Getters and Setters
}