This commit is contained in:
parent
def8ac7a6c
commit
b6f9386dd6
|
@ -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 "";
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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='系统操作日志';
|
Loading…
Reference in New Issue