|
|
|
@ -27,54 +27,81 @@ import org.springframework.stereotype.Component;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SysLogAspect类,用于实现系统日志记录的切面功能。
|
|
|
|
|
* 通过AOP(面向切面编程)的方式,拦截被特定注解标记的方法,在方法执行前后进行相关操作,
|
|
|
|
|
* 主要用于收集系统操作的相关信息并保存为系统日志,方便后续的审计、排查问题等操作。
|
|
|
|
|
*
|
|
|
|
|
* @author lgh
|
|
|
|
|
*/
|
|
|
|
|
@Aspect
|
|
|
|
|
@Component
|
|
|
|
|
public class SysLogAspect {
|
|
|
|
|
@Autowired
|
|
|
|
|
private SysLogService sysLogService;
|
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
|
|
|
|
|
|
|
|
|
|
@Around("@annotation(sysLog)")
|
|
|
|
|
public Object around(ProceedingJoinPoint joinPoint,com.yami.shop.common.annotation.SysLog sysLog) throws Throwable {
|
|
|
|
|
long beginTime = SystemClock.now();
|
|
|
|
|
//执行方法
|
|
|
|
|
Object result = joinPoint.proceed();
|
|
|
|
|
//执行时长(毫秒)
|
|
|
|
|
long time = SystemClock.now() - beginTime;
|
|
|
|
|
// 自动注入SysLogService,用于将收集到的日志信息保存到数据库等存储介质中
|
|
|
|
|
@Autowired
|
|
|
|
|
private SysLogService sysLogService;
|
|
|
|
|
|
|
|
|
|
// 使用SLF4J的Logger来记录日志信息,方便在出现问题或者调试时输出相关的提示信息
|
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Around注解表示这是一个环绕通知方法,它会在目标方法执行前后进行增强处理。
|
|
|
|
|
* 这里拦截了被@SysLog注解标记的方法,在方法执行前记录开始时间,执行后计算执行时长,
|
|
|
|
|
* 并收集如操作描述、请求方法名、参数、IP地址、用户名等信息,封装成SysLog对象后保存到系统日志中。
|
|
|
|
|
*
|
|
|
|
|
* @param joinPoint 连接点对象,通过它可以获取目标方法的相关信息,如方法名、参数等
|
|
|
|
|
* @param sysLog 被拦截方法上标注的@SysLog注解对象,用于获取操作描述信息
|
|
|
|
|
* @return 目标方法执行的结果,保证原方法的执行逻辑不受影响并能将结果正确返回给调用者
|
|
|
|
|
* @throws Throwable 如果目标方法执行过程中抛出异常,会在这里继续向上抛出,保证异常处理机制正常工作
|
|
|
|
|
*/
|
|
|
|
|
@Around("@annotation(sysLog)")
|
|
|
|
|
public Object around(ProceedingJoinPoint joinPoint, com.yami.shop.common.annotation.SysLog sysLog) throws Throwable {
|
|
|
|
|
// 获取方法执行前的时间戳(使用SystemClock.now()获取更精准的时间,可能比System.currentTimeMillis()性能更好)
|
|
|
|
|
long beginTime = SystemClock.now();
|
|
|
|
|
|
|
|
|
|
// 执行被拦截的目标方法,获取其返回结果。如果目标方法有异常抛出,会在这里直接抛出,后续代码不会执行
|
|
|
|
|
Object result = joinPoint.proceed();
|
|
|
|
|
|
|
|
|
|
// 计算方法执行所花费的时间(单位:毫秒),通过当前时间减去方法开始执行的时间得到
|
|
|
|
|
long time = SystemClock.now() - beginTime;
|
|
|
|
|
|
|
|
|
|
// 创建一个SysLog实体对象,用于封装要保存的系统日志信息
|
|
|
|
|
SysLog sysLogEntity = new SysLog();
|
|
|
|
|
|
|
|
|
|
SysLog sysLogEntity = new SysLog();
|
|
|
|
|
if(sysLog != null){
|
|
|
|
|
//注解上的描述
|
|
|
|
|
sysLogEntity.setOperation(sysLog.value());
|
|
|
|
|
}
|
|
|
|
|
// 如果被拦截的方法上标注的@SysLog注解不为空,则将注解中的描述信息设置为系统日志的操作描述
|
|
|
|
|
if (sysLog!= null) {
|
|
|
|
|
// 注解上的描述,通常是对该操作的简要说明,例如“用户登录操作”等
|
|
|
|
|
sysLogEntity.setOperation(sysLog.value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//请求的方法名
|
|
|
|
|
String className = joinPoint.getTarget().getClass().getName();
|
|
|
|
|
String methodName = joinPoint.getSignature().getName();
|
|
|
|
|
sysLogEntity.setMethod(className + "." + methodName + "()");
|
|
|
|
|
// 获取请求的方法名,通过连接点对象获取目标类的全限定名以及方法名,拼接成完整的方法调用表示形式
|
|
|
|
|
String className = joinPoint.getTarget().getClass().getName();
|
|
|
|
|
String methodName = joinPoint.getSignature().getName();
|
|
|
|
|
sysLogEntity.setMethod(className + "." + methodName + "()");
|
|
|
|
|
|
|
|
|
|
//请求的参数
|
|
|
|
|
Object[] args = joinPoint.getArgs();
|
|
|
|
|
String params = Json.toJsonString(args[0]);
|
|
|
|
|
sysLogEntity.setParams(params);
|
|
|
|
|
// 获取请求的参数,通过连接点对象获取方法的参数数组,这里将参数转换为JSON字符串进行存储(方便查看参数详情),
|
|
|
|
|
// 目前只取了参数数组中的第一个元素进行转换,如果参数有多个可能需要更完善的处理逻辑
|
|
|
|
|
Object[] args = joinPoint.getArgs();
|
|
|
|
|
String params = Json.toJsonString(args[0]);
|
|
|
|
|
sysLogEntity.setParams(params);
|
|
|
|
|
|
|
|
|
|
//设置IP地址
|
|
|
|
|
sysLogEntity.setIp(IpHelper.getIpAddr());
|
|
|
|
|
// 设置IP地址,通过IpHelper工具类获取客户端的IP地址信息,并设置到系统日志实体中
|
|
|
|
|
sysLogEntity.setIp(IpHelper.getIpAddr());
|
|
|
|
|
|
|
|
|
|
//用户名
|
|
|
|
|
String username = SecurityUtils.getSysUser().getUsername();
|
|
|
|
|
sysLogEntity.setUsername(username);
|
|
|
|
|
// 获取用户名,通过SecurityUtils工具类获取当前登录系统的用户信息,再获取用户名,设置到系统日志实体中
|
|
|
|
|
String username = SecurityUtils.getSysUser().getUsername();
|
|
|
|
|
sysLogEntity.setUsername(username);
|
|
|
|
|
|
|
|
|
|
sysLogEntity.setTime(time);
|
|
|
|
|
sysLogEntity.setCreateDate(new Date());
|
|
|
|
|
//保存系统日志
|
|
|
|
|
sysLogService.save(sysLogEntity);
|
|
|
|
|
// 设置方法执行时长(单位:毫秒)到系统日志实体中
|
|
|
|
|
sysLogEntity.setTime(time);
|
|
|
|
|
|
|
|
|
|
// 设置系统日志的创建日期,使用当前时间作为创建时间
|
|
|
|
|
sysLogEntity.setCreateDate(new Date());
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
// 调用SysLogService的save方法,将封装好的系统日志实体保存到数据库或者其他存储介质中,实现系统日志记录功能
|
|
|
|
|
sysLogService.save(sysLogEntity);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 返回目标方法执行的结果,保证原方法调用链的正常返回逻辑
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|