springboot 日志类切面,接口成功记录日志,失败不记录
自定义一个注解方法
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <描述> 标记需要记录日志的方法
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogOperation {
String detail() default "";//内容
String type() default "";//类型
String modName() default "";//模块名称
boolean add() default true;
}
主要的切面类
我这里获取了Authentication 用于添加farmId和userId ,可以根据自己的方法替换或删除这部分
我其他接口统一返回用了 自定义的返回类Ret,所以这里判断了Ret 返回状态
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import java.util.ArrayList;
import java.util.List;
/**
* 日志-切面类
*/
@Aspect
@Component
@Slf4j
public class LoggingAspect {
@Autowired
private SysLogService sysLogService;
//暂定设置默认的参数
private static final int DEFAULT_FARM_ID = 0;
private static final int DEFAULT_USER_ID = 0;
@Around("@annotation(logOperation)")
public Object logAround(ProceedingJoinPoint joinPoint, LogOperation logOperation) throws Throwable {
log.info("--------------------记录日志开始------------------------------------");
//初始化日志类
SysLog sysLog = new SysLog();
long startTime = System.currentTimeMillis();
try {
// 获取 Authentication 用于添加farmId和userId
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
SysAccount account = (auth != null && auth.getPrincipal() instanceof SysAccount) ?
(SysAccount) auth.getPrincipal() : null;
if (account != null) {
sysLog.setFarmId(account.getFarmId());
sysLog.setUserId(account.getUserId());
} else {
log.warn("Authentication 或 principal 为 null,无法获取 SysAccount,设置默认参数 0 ");
sysLog.setFarmId(DEFAULT_FARM_ID);
sysLog.setUserId(DEFAULT_USER_ID);
}
// 检查 LogOperation 的各个字段是否为空
String text = (logOperation != null && logOperation.detail() != null) ?
logOperation.detail() : "";
String type = (logOperation != null && logOperation.type() != null) ?
logOperation.type() : "";
String modName = (logOperation != null && logOperation.modName() != null) ?
logOperation.modName() : "";
sysLog.setType(type);
sysLog.setModName(modName);
sysLog.setDetail(text);
// 执行目标方法并捕获结果
Object result = joinPoint.proceed();
// 接口统一返回的都是Ret,这里检查返回结果是否为 Ret,并判断状态
if (result instanceof Ret) {
Ret ret = (Ret) result;
// 如果返回状态为 fail,则不记录日志
if (ret.isFail()) {
log.info("--------------------记录日志结束(请求失败,不记录日志)------------------------------------");
return result; // 返回原结果,不进行日志记录
}
// 如果状态为 ok,则记录日志
Object[] args = joinPoint.getArgs(); // 获取方法参数
List<String> filteredArgs = new ArrayList<>();
for (Object arg : args) {
if (!(arg instanceof Authentication || arg instanceof BeanPropertyBindingResult)) {
filteredArgs.add(arg != null ? arg.toString() : "null");
}
}
String jsonArgs;
try {
jsonArgs = JSON.toJSONString(filteredArgs); // 转换参数为 JSON 字符串
} catch (Exception e) {
log.error("JSON转换出错: {}", e.getMessage());
jsonArgs = "无法序列化参数"; // 设定默认值
}
sysLog.setDetail(text + "-参数:" + jsonArgs);
//执行日志添加
sysLogService.save(sysLog);
} else {
log.warn("返回结果不是 Ret 类型,无法判断状态");
}
return result;
} catch (Throwable throwable) {
log.error("日志记录失败: {}", throwable.getMessage(), throwable);
throw throwable;
} finally {
//记录执行时间已经标志结束
long endTime = System.currentTimeMillis();
log.info("方法执行时间:{} ms", endTime - startTime);
log.info("--------------------记录日志结束------------------------------------");
}
}
}
具体调用逻辑
也可以根据需求加注解内的字段