feat(sysapi): 添加接口日志归档功能
- 创建 SysApiLogHistory 实体类用于存储历史日志数据 - 实现 ISysApiLogHistoryService 和相关 Mapper 接口 - 添加 SysApiLogHistoryServiceImpl 业务逻辑实现 - 在 SysApiLogService 中新增 archiveLogs 方法实现归档逻辑 - 更新 SysApiLogController 支持日志归档接口调用 - 实现按系统参数配置的保留天数自动迁移旧日志数据 - 添加事务支持确保归档过程的数据一致性 - 集成 SpringContextHolder 用于获取系统参数配置
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.nl.system.controller.sysapi;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -7,11 +8,16 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.common.domain.query.PageQuery;
|
||||
import org.nl.modules.logging.annotation.Log;
|
||||
import org.nl.modules.wql.util.SpringContextHolder;
|
||||
import org.nl.system.service.param.impl.SysParamServiceImpl;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLog;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
|
||||
import org.nl.system.service.sysapi.entity.dto.ApiLogQuery;
|
||||
import org.nl.system.service.sysapi.service.ISysApiLogHistoryService;
|
||||
import org.nl.system.service.sysapi.service.ISysApiLogService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -31,6 +37,8 @@ public class SysApiLogController {
|
||||
|
||||
private final ISysApiLogService apiLogService;
|
||||
|
||||
private final ISysApiLogHistoryService apiLogHistoryService;
|
||||
|
||||
/**
|
||||
* 分页查询接口日志列表
|
||||
*/
|
||||
@@ -135,25 +143,8 @@ public class SysApiLogController {
|
||||
*/
|
||||
@PostMapping("/archive")
|
||||
@Log("接口日志归档")
|
||||
public ResponseEntity<Void> archiveLogs() {
|
||||
try {
|
||||
LambdaQueryWrapper<SysApiLog> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.lt(SysApiLog::getCreateTime,
|
||||
java.time.LocalDateTime.now().minusDays(30).toString().replace('T', ' '));
|
||||
|
||||
List<SysApiLog> oldLogs = apiLogService.list(wrapper);
|
||||
|
||||
if (!oldLogs.isEmpty()) {
|
||||
log.info("开始归档接口日志,共 {} 条数据", oldLogs.size());
|
||||
// TODO: 这里可以实现归档逻辑,比如:
|
||||
// 1. 备份到历史表 sys_api_log_history
|
||||
apiLogService.remove(wrapper);
|
||||
log.info("接口日志归档完成,已删除 {} 条旧数据", oldLogs.size());
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
log.error("接口日志归档失败", e);
|
||||
throw new RuntimeException("日志归档失败: " + e.getMessage());
|
||||
}
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseEntity archiveLogs() {
|
||||
return apiLogService.archiveLogs();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.nl.system.service.sysapi.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import lombok.Data;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 接口日志对象 sys_api_log_history
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
@TableName("sys_api_log_history")
|
||||
public class SysApiLogHistory implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId("log_id")
|
||||
private String logId;
|
||||
|
||||
@TableField("direction")
|
||||
private Integer direction;
|
||||
|
||||
@TableField("system_flag")
|
||||
private String systemFlag;
|
||||
|
||||
@TableField("biz_code")
|
||||
private String bizCode;
|
||||
|
||||
@TableField("biz_desc")
|
||||
private String bizDesc;
|
||||
|
||||
@TableField("api_url")
|
||||
private String apiUrl;
|
||||
|
||||
@TableField("api_desc")
|
||||
private String apiDesc;
|
||||
|
||||
@TableField("trace_id")
|
||||
private String traceId;
|
||||
|
||||
@TableField("request_method")
|
||||
private String requestMethod;
|
||||
|
||||
@TableField("request_ip")
|
||||
private String requestIp;
|
||||
|
||||
@TableField("request_headers")
|
||||
private String requestHeaders;
|
||||
|
||||
@TableField("request_params")
|
||||
private String requestParams;
|
||||
|
||||
@TableField("response_body")
|
||||
private String responseBody;
|
||||
|
||||
@TableField("response_status")
|
||||
private Integer responseStatus;
|
||||
|
||||
@TableField("cost_time")
|
||||
private Long costTime;
|
||||
|
||||
@TableField("status")
|
||||
private String status;
|
||||
|
||||
@TableField("error_msg")
|
||||
private String errorMsg;
|
||||
|
||||
@TableField("operator")
|
||||
private String operator;
|
||||
|
||||
@TableField("create_time")
|
||||
private String createTime;
|
||||
|
||||
//copy method
|
||||
public static SysApiLogHistory adapter(SysApiLog sysApiLog){
|
||||
SysApiLogHistory sysApiLogHistory = new SysApiLogHistory();
|
||||
BeanUtils.copyProperties(sysApiLog,sysApiLogHistory);
|
||||
return sysApiLogHistory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.nl.system.service.sysapi.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
|
||||
|
||||
/**
|
||||
* 接口日志Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
public interface SysApiLogHistoryMapper extends BaseMapper<SysApiLogHistory> {
|
||||
/**
|
||||
* 查询接口日志
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 接口日志
|
||||
*/
|
||||
public SysApiLogHistory selectSysApiLogHistoryByLogId(String logId);
|
||||
|
||||
/**
|
||||
* 查询接口日志列表
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 接口日志集合
|
||||
*/
|
||||
public List<SysApiLogHistory> selectSysApiLogHistoryList(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 新增接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSysApiLogHistory(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 修改接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSysApiLogHistory(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 删除接口日志
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysApiLogHistoryByLogId(String logId);
|
||||
|
||||
/**
|
||||
* 批量删除接口日志
|
||||
*
|
||||
* @param logIds 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysApiLogHistoryByLogIds(String[] logIds);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.nl.system.service.sysapi.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
|
||||
|
||||
/**
|
||||
* 接口日志Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
public interface ISysApiLogHistoryService extends IService<SysApiLogHistory> {
|
||||
/**
|
||||
* 查询接口日志
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 接口日志
|
||||
*/
|
||||
public SysApiLogHistory selectSysApiLogHistoryByLogId(String logId);
|
||||
|
||||
/**
|
||||
* 查询接口日志列表
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 接口日志集合
|
||||
*/
|
||||
public List<SysApiLogHistory> selectSysApiLogHistoryList(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 新增接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int insertSysApiLogHistory(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 修改接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateSysApiLogHistory(SysApiLogHistory sysApiLogHistory);
|
||||
|
||||
/**
|
||||
* 批量删除接口日志
|
||||
*
|
||||
* @param logIds 需要删除的接口日志主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysApiLogHistoryByLogIds(String[] logIds);
|
||||
|
||||
/**
|
||||
* 删除接口日志信息
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteSysApiLogHistoryByLogId(String logId);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.nl.system.service.sysapi.service;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLog;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
/**
|
||||
@@ -14,4 +16,6 @@ public interface ISysApiLogService extends IService<SysApiLog> {
|
||||
|
||||
@Async("apiLogExecutor")
|
||||
void saveAsync(SysApiLog apiLog);
|
||||
|
||||
ResponseEntity<T> archiveLogs();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.nl.system.service.sysapi.service;
|
||||
|
||||
import com.alibaba.fastjson2.util.DateUtils;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import java.util.List;
|
||||
|
||||
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
|
||||
import org.nl.system.service.sysapi.mapper.SysApiLogHistoryMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 接口日志Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
@Service
|
||||
public class SysApiLogHistoryServiceImpl extends ServiceImpl<SysApiLogHistoryMapper, SysApiLogHistory> implements ISysApiLogHistoryService {
|
||||
@Autowired
|
||||
private SysApiLogHistoryMapper sysApiLogHistoryMapper;
|
||||
|
||||
/**
|
||||
* 查询接口日志
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 接口日志
|
||||
*/
|
||||
@Override
|
||||
public SysApiLogHistory selectSysApiLogHistoryByLogId(String logId) {
|
||||
return sysApiLogHistoryMapper.selectSysApiLogHistoryByLogId(logId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询接口日志列表
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 接口日志
|
||||
*/
|
||||
@Override
|
||||
public List<SysApiLogHistory> selectSysApiLogHistoryList(SysApiLogHistory sysApiLogHistory) {
|
||||
return sysApiLogHistoryMapper.selectSysApiLogHistoryList(sysApiLogHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int insertSysApiLogHistory(SysApiLogHistory sysApiLogHistory) {
|
||||
return sysApiLogHistoryMapper.insertSysApiLogHistory(sysApiLogHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口日志
|
||||
*
|
||||
* @param sysApiLogHistory 接口日志
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int updateSysApiLogHistory(SysApiLogHistory sysApiLogHistory) {
|
||||
return sysApiLogHistoryMapper.updateSysApiLogHistory(sysApiLogHistory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除接口日志
|
||||
*
|
||||
* @param logIds 需要删除的接口日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSysApiLogHistoryByLogIds(String[] logIds) {
|
||||
return sysApiLogHistoryMapper.deleteSysApiLogHistoryByLogIds(logIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口日志信息
|
||||
*
|
||||
* @param logId 接口日志主键
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteSysApiLogHistoryByLogId(String logId) {
|
||||
return sysApiLogHistoryMapper.deleteSysApiLogHistoryByLogId(logId);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,26 @@
|
||||
package org.nl.system.service.sysapi.service;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
import org.nl.common.utils.IdUtil;
|
||||
import org.nl.modules.wql.util.SpringContextHolder;
|
||||
import org.nl.system.service.param.impl.SysParamServiceImpl;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLog;
|
||||
import org.nl.system.service.sysapi.entity.SysApiLogHistory;
|
||||
import org.nl.system.service.sysapi.mapper.SysApiLogHistoryMapper;
|
||||
import org.nl.system.service.sysapi.mapper.SysApiLogMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author ManMan.Yang
|
||||
@@ -20,6 +34,9 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
public class SysApiLogServiceImpl extends ServiceImpl<SysApiLogMapper, SysApiLog> implements ISysApiLogService {
|
||||
|
||||
@Autowired
|
||||
private ISysApiLogHistoryService sysApiLogHistoryService;
|
||||
|
||||
@Override
|
||||
@Async("apiLogExecutor")
|
||||
public void saveAsync(SysApiLog apiLog) {
|
||||
@@ -35,4 +52,43 @@ public class SysApiLogServiceImpl extends ServiceImpl<SysApiLogMapper, SysApiLog
|
||||
log.error("保存接口日志失败, logId: {}", apiLog.getLogId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseEntity<T> archiveLogs() {
|
||||
try {
|
||||
// 获取系统配置的日志保留天数
|
||||
String days = SpringContextHolder.getBean(SysParamServiceImpl.class).findByCode("sys_api_keep_days").getValue();
|
||||
if(StrUtil.isEmpty( days)){
|
||||
days = "60";
|
||||
}
|
||||
int keepDays = Integer.parseInt(days);
|
||||
LambdaQueryWrapper<SysApiLog> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.lt(SysApiLog::getCreateTime,
|
||||
java.time.LocalDateTime.now().minusDays(keepDays).toString().replace('T', ' '));
|
||||
List<SysApiLog> oldLogs = this.list(wrapper);
|
||||
if (!oldLogs.isEmpty()) {
|
||||
log.info("开始归档接口日志,共 {} 条数据", oldLogs.size());
|
||||
/*
|
||||
* 88549333 接口日志归档,防止数据量过大对插入和查询造成性能损耗
|
||||
* 1. 批量保存到历史表 sys_api_log_history
|
||||
* 2. 删除旧数据
|
||||
*/
|
||||
// 1. 备份到历史表 sys_api_log_history
|
||||
List<SysApiLogHistory> historyList = oldLogs.stream().map(SysApiLogHistory::adapter).collect(Collectors.toList());
|
||||
boolean saveSuccess = sysApiLogHistoryService.saveBatch(historyList);
|
||||
if (saveSuccess) {
|
||||
this.remove(wrapper);
|
||||
log.info("接口日志归档完成,已迁移并删除 {} 条旧数据", oldLogs.size());
|
||||
} else {
|
||||
log.error("接口日志归档失败,保存历史数据失败");
|
||||
throw new RuntimeException("保存历史数据失败");
|
||||
}
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
log.error("接口日志归档失败", e);
|
||||
throw new RuntimeException("日志归档失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user