This commit is contained in:
ovo 2024-12-07 19:03:14 +08:00
parent def8ac7a6c
commit b6f9386dd6
5 changed files with 185 additions and 0 deletions

View File

@ -0,0 +1,18 @@
package com.guwan.backend.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
/**
* 操作描述
*/
String description() default "";
/**
* 操作类型新增修改删除查询等
*/
String operationType() default "";
}

View File

@ -0,0 +1,108 @@
package com.guwan.backend.aspect;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.entity.SysLog;
import com.guwan.backend.mapper.SysLogMapper;
import com.guwan.backend.security.CustomUserDetails;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Arrays;
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class OperationLogAspect {
private final SysLogMapper sysLogMapper;
private final ObjectMapper objectMapper;
@Around("@annotation(operationLog)")
public Object around(ProceedingJoinPoint point, OperationLog operationLog) throws Throwable {
long beginTime = System.currentTimeMillis();
SysLog sysLog = new SysLog();
try {
// 执行方法
Object result = point.proceed();
// 设置状态为成功
sysLog.setStatus(1);
return result;
} catch (Exception e) {
// 记录异常信息
sysLog.setStatus(0);
sysLog.setErrorMsg(e.getMessage());
throw e;
} finally {
// 记录日志
saveLog(point, operationLog, beginTime, sysLog);
}
}
private void saveLog(ProceedingJoinPoint joinPoint, OperationLog operationLog, long beginTime, SysLog sysLog) {
try {
// 获取当前请求
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
sysLog.setIp(getIpAddress(request));
sysLog.setUserAgent(request.getHeader("User-Agent"));
}
// 获取当前用户信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getPrincipal() instanceof CustomUserDetails) {
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
sysLog.setUserId(userDetails.getUserId());
sysLog.setUsername(userDetails.getUsername());
}
// 获取方法信息
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
sysLog.setMethod(method.getDeclaringClass().getName() + "." + method.getName());
// 获取请求参数
String params = Arrays.toString(joinPoint.getArgs());
sysLog.setParams(params.length() > 2000 ? params.substring(0, 2000) : params);
// 设置操作信息
sysLog.setOperation(operationLog.description());
sysLog.setCreateTime(LocalDateTime.now());
sysLog.setTimeConsuming(System.currentTimeMillis() - beginTime);
// 保存日志
sysLogMapper.insert(sysLog);
} catch (Exception e) {
log.error("记录操作日志失败", e);
}
}
private String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

View File

@ -0,0 +1,37 @@
package com.guwan.backend.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_log")
public class SysLog {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private String username;
private String operation;
private String method;
private String params;
private String ip;
private String location;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
private Long timeConsuming;
private String userAgent;
private Integer status;
private String errorMsg;
}

View File

@ -1,11 +1,13 @@
package com.guwan.backend.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.guwan.backend.annotation.OperationLog;
import com.guwan.backend.dto.user.LoginDto;
import com.guwan.backend.dto.user.RegisterDTO;
import com.guwan.backend.dto.user.UserDTO;
import com.guwan.backend.entity.User;
import com.guwan.backend.mapper.UserMapper;
import com.guwan.backend.security.CustomUserDetails;
import com.guwan.backend.service.EmailService;
import com.guwan.backend.service.UserService;
import com.guwan.backend.service.VerificationService;
@ -46,6 +48,7 @@ public class UserServiceImpl implements UserService {
@Override
@Transactional
@OperationLog(description = "用户注册", operationType = "注册")
public UserDTO register(RegisterDTO request) {
// 检查用户名是否已存在
if (findByUsername(request.getUsername()) != null) {
@ -93,6 +96,7 @@ public class UserServiceImpl implements UserService {
}
@Override
@OperationLog(description = "用户登录", operationType = "登录")
public UserDTO login(LoginDto request) {
User user = null;
System.out.println("request = " + request);

View File

@ -0,0 +1,18 @@
CREATE TABLE `sys_log` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '日志ID',
`user_id` bigint DEFAULT NULL COMMENT '用户ID',
`username` varchar(50) DEFAULT NULL COMMENT '用户名',
`operation` varchar(50) DEFAULT NULL COMMENT '操作',
`method` varchar(200) DEFAULT NULL COMMENT '方法名',
`params` varchar(2000) DEFAULT NULL COMMENT '参数',
`ip` varchar(64) DEFAULT NULL COMMENT 'IP地址',
`location` varchar(255) DEFAULT NULL COMMENT '操作地点',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`time_consuming` bigint DEFAULT NULL COMMENT '耗时(毫秒)',
`user_agent` varchar(500) DEFAULT NULL COMMENT '用户代理',
`status` tinyint DEFAULT NULL COMMENT '状态(1-成功,0-失败)',
`error_msg` varchar(2000) DEFAULT NULL COMMENT '错误信息',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统操作日志';