feat(core): 完善日志切面并优化日志实体

- 在 LogAspect 中添加了请求参数和响应内容的记录
- 增加 Log 实体类的字段
This commit is contained in:
谢东
2024-12-06 00:25:26 +08:00
parent e9e2276841
commit 7aa206b120
2 changed files with 110 additions and 50 deletions

View File

@@ -5,19 +5,29 @@ import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.HttpMethod;
import com.youlai.boot.common.constant.SecurityConstants;
import com.youlai.boot.common.util.IPUtils;
import com.youlai.boot.system.model.entity.Log;
import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.system.model.entity.Log;
import com.youlai.boot.system.service.LogService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import java.util.Collection;
import java.util.Map;
/**
* 日志切面
@@ -38,8 +48,13 @@ public class LogAspect {
public void logPointcut() {
}
@Around("logPointcut() && @annotation(logAnnotation)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint, com.youlai.boot.core.annotation.Log logAnnotation) throws Throwable {
/**
* 处理完请求后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointcut() && @annotation(logAnnotation)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, com.youlai.boot.core.annotation.Log logAnnotation, Object jsonResult) {
String requestURI = request.getRequestURI();
Long userId = null;
@@ -50,7 +65,6 @@ public class LogAspect {
TimeInterval timer = DateUtil.timer();
// 执行方法
Object proceed = joinPoint.proceed();
long executionTime = timer.interval();
// 创建日志记录
@@ -76,6 +90,8 @@ public class LogAspect {
}
}
}
this.setRequestParameters(joinPoint, log);
log.setResponseContent(JSONUtil.toJsonStr(jsonResult));
log.setExecutionTime(executionTime);
// 获取浏览器和终端系统信息
String userAgentString = request.getHeader("User-Agent");
@@ -88,8 +104,67 @@ public class LogAspect {
// 保存日志到数据库
logService.save(log);
return proceed;
}
/**
* 设置请求参数到日志对象中
*
* @param joinPoint 切点
* @param log 操作日志
*/
private void setRequestParameters(JoinPoint joinPoint, Log log) {
String requestMethod = request.getMethod();
log.setRequestMethod(requestMethod);
if (HttpMethod.GET.name().equalsIgnoreCase(requestMethod) || HttpMethod.PUT.name().equalsIgnoreCase(requestMethod) || HttpMethod.POST.name().equalsIgnoreCase(requestMethod)) {
String params = convertArgumentsToString(joinPoint.getArgs());
log.setRequestParams(StrUtil.sub(params, 0, 65535));
} else {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
Map<?, ?> paramsMap = (Map<?, ?>) attributes.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
log.setRequestParams(StrUtil.sub(paramsMap.toString(), 0, 65535));
} else {
log.setRequestParams("");
}
}
}
/**
* 将参数数组转换为字符串
*
* @param paramsArray 参数数组
* @return 参数字符串
*/
private String convertArgumentsToString(Object[] paramsArray) {
StringBuilder params = new StringBuilder();
if (paramsArray != null) {
for (Object param : paramsArray) {
if (!shouldFilterObject(param)) {
params.append(JSONUtil.toJsonStr(param)).append(" ");
}
}
}
return params.toString().trim();
}
/**
* 判断是否需要过滤的对象。
*
* @param obj 对象信息。
* @return 如果是需要过滤的对象则返回true否则返回false。
*/
private boolean shouldFilterObject(Object obj) {
Class<?> clazz = obj.getClass();
if (clazz.isArray()) {
return MultipartFile.class.isAssignableFrom(clazz.getComponentType());
} else if (Collection.class.isAssignableFrom(clazz)) {
Collection<?> collection = (Collection<?>) obj;
return collection.stream().anyMatch(item -> item instanceof MultipartFile);
} else if (Map.class.isAssignableFrom(clazz)) {
Map<?, ?> map = (Map<?, ?>) obj;
return map.values().stream().anyMatch(value -> value instanceof MultipartFile);
}
return obj instanceof MultipartFile || obj instanceof HttpServletRequest || obj instanceof HttpServletResponse;
}
}

View File

@@ -1,13 +1,13 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.youlai.boot.common.enums.LogModuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.youlai.boot.common.enums.LogModuleEnum;
import lombok.Data;
/**
* 系统日志 实体类
*
@@ -17,72 +17,57 @@ import lombok.Data;
@TableName("sys_log")
@Data
public class Log implements Serializable {
/**
* 主键
*/
@Schema(description = "主键")
@TableId(type = IdType.AUTO)
private Long id;
/**
* 日志模块
*/
@Schema(description = "日志模块")
private LogModuleEnum module;
@Schema(description = "请求方式")
@TableField(value = "request_method")
private String requestMethod;
/**
* 日志内容
*/
@Schema(description = "请求参数")
@TableField(value = "request_params")
private String requestParams;
@Schema(description = "响应参数")
@TableField(value = "response_content")
private String responseContent;
@Schema(description = "日志内容")
private String content;
/**
* 请求路径
*/
@Schema(description = "请求路径")
private String requestUri;
/**
* IP 地址
*/
@Schema(description = "IP 地址")
private String ip;
/**
* 省份
*/
@Schema(description = "省份")
private String province;
/**
* 城市
*/
@Schema(description = "城市")
private String city;
/**
* 浏览器
*/
@Schema(description = "浏览器")
private String browser;
/**
* 浏览器版本
*/
@Schema(description = "浏览器版本")
private String browserVersion;
/**
* 终端系统
*/
@Schema(description = "终端系统")
private String os;
/**
* 执行时间(毫秒)
*/
@Schema(description = "执行时间(毫秒)")
private Long executionTime;
/**
* 创建人ID
*/
@Schema(description = "创建人ID")
private Long createBy;
/**
* 创建时间
*/
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;