一:依赖
<!-- 操作日志依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.13</version>
</dependency>
<!-- JWT依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
二:实体类
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* <p>
* 操作日志记录表
* </p>
*
* @since 2024-08-31
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_log_record_do")
@ApiModel(value="UserLogRecordDo对象", description="操作日志记录表")
public class UserLogRecordDo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "行为描述")
private String action;
@ApiModelProperty(value = "执行入参")
private String methodParams;
@ApiModelProperty(value = "响应编码")
private String resultCode;
@ApiModelProperty(value = "结果描述")
private String resultMsg;
@ApiModelProperty(value = "操作人ID")
private Long operateUserId;
@ApiModelProperty(value = "操作人名称")
private String operateUserName;
@ApiModelProperty(value = "操作时间")
private LocalDateTime operateTime;
@ApiModelProperty(value = "资源路径")
private String requestUri;
@ApiModelProperty(value = "用户ip地址")
private String remoteHost;
@ApiModelProperty(value = "获取请求的方式")
private String method;
@ApiModelProperty(value = "操作耗时")
private Long costTime;
}
三:异常
import lombok.Data;
import lombok.Getter;
@Getter
@Data
public class BusinessException extends RuntimeException{
private String code;
private boolean isShowMsg = true;
}
四:枚举
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
// 1.操作描述
String action() default "";
// 3.是否记录参数
boolean isRecord() default true;
}
五:代码实现
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
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.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.example.demo.register.JwtUtils;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
@Slf4j
@Aspect
@Component
public class AuditAspect {
@Resource
private UserLogRecordDoMapper userLogRecordDoMapper;
@Resource
private HttpServletRequest httpServletRequest;
@Pointcut(value = "@annotation(com.example.demo.operationLog2.AuditLog)")
public void logMethodPointCut() {
}
@Around("logMethodPointCut()")
public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {
//原始方法运行前
long begin = System.currentTimeMillis();
UserLogRecordDo userLogRecordDO = bulidRequestParams(point);
//操作人ID - 当前登录员ID
String jwt = httpServletRequest.getHeader("token");
Claims claims = JwtUtils.parseJWT(jwt);
Integer userId = (Integer) claims.get("id");
String userName = (String) claims.get("userName");
Long userIdL = Long.valueOf(userId);
userLogRecordDO.setOperateUserId(userIdL);
userLogRecordDO.setOperateUserName(userName);
//操作时间
LocalDateTime operateTime = LocalDateTime.now();
userLogRecordDO.setOperateTime(operateTime);
//资源路径
String requestURI = httpServletRequest.getRequestURI();
userLogRecordDO.setRequestUri(requestURI);
//用户ip地址
String remoteHost = httpServletRequest.getRemoteHost();
userLogRecordDO.setRemoteHost(remoteHost);
//获取请求的方式
String method = httpServletRequest.getMethod();
userLogRecordDO.setMethod(method);
//操作方法参数
Object[] args = point.getArgs();
String methodParams = Arrays.toString(args);
String substring = methodParams.substring(1, methodParams.length() - 1);
userLogRecordDO.setMethodParams(substring);
//先执行业务
try {
Object result = point.proceed();
if (result != null) {
userLogRecordDO.setResultMsg(JSONUtil.toJsonStr(result));
}
return result;
} catch (BusinessException e) {
userLogRecordDO.setResultCode(e.getCode());
userLogRecordDO.setResultMsg(e.getMessage());
throw e;
} catch (Exception e) {
userLogRecordDO.setResultCode("500");
userLogRecordDO.setResultMsg(e + "");
throw e;
} finally {
//操作日志入库
try {
//原始方法运行后
long end = System.currentTimeMillis();
//操作耗时
Long costTime = end - begin;
userLogRecordDO.setCostTime(costTime);
userLogRecordDO.setResultCode("200");
userLogRecordDoMapper.insert(userLogRecordDO);
} catch (Exception e) {
log.warn("记录用户操作异常:{}", e.getMessage());
}
}
}
/**
* 记录方法和方法入参
* @param point
* @return
*/
protected UserLogRecordDo bulidRequestParams(ProceedingJoinPoint point) {
MethodSignature methodSignature = (MethodSignature) point.getSignature();
Method method = methodSignature.getMethod();
AuditLog annotation = method.getAnnotation(AuditLog.class);
UserLogRecordDo userLogRecordDO = new UserLogRecordDo();
userLogRecordDO.setAction(annotation.action());
try {
// 处理入参
Parameter[] parameters = methodSignature.getMethod().getParameters();
HashMap<String, Object> paramMap = new HashMap<>();
Object[] args = point.getArgs();
for (int i = 0; i < parameters.length; i++) {
AuditLog auditLog = parameters[i].getAnnotation(AuditLog.class);
if (auditLog != null) {
continue;
}
Class<?> type = parameters[i].getType();
if (ServletResponse.class.isAssignableFrom(type) || ServletRequest.class.isAssignableFrom(type)) {
continue;
}
String name = parameters[i].getName();
paramMap.put(name, args[i]);
}
userLogRecordDO.setMethodParams(JSONUtil.toJsonStr(paramMap));
return userLogRecordDO;
} catch (Exception e) {
log.warn("构建入参异常:{}", e.getMessage());
}
return userLogRecordDO;
}
}
六:使用注解
![](https://i-blog.csdnimg.cn/direct/ac2baa22a1d346afac8ee77dfee94d13.png)