在基于Spring Boot的项目开发中,日志记录是一个非常重要的方面。为了规范和简化日志记录的过程,我们可以利用Spring Boot的AOP(面向切面编程)功能来实现统一的日志处理。
首先,我们需要创建一个切面类,并使用 @Aspect
和 @Component
注解进行标识。切面类的作用是定义切点和通知,以便在特定方法执行前后添加额外的日志逻辑。
@Aspect
@Component
public class LogAspect {
// ...
}
接下来,我们定义一个切点,用于匹配带有 @Log
注解的方法,该注解用于标识需要记录日志的方法。
@Pointcut("@annotation(com.xiaoke.annotation.Log)")
public void pt() {
}
然后,我们使用 @Around
注解来实现环绕通知,该通知会在切点方法执行前后进行拦截,并在执行完切点方法后记录日志信息。在拦截到切点方法后,我们可以通过 ProceedingJoinPoint
对象获取方法的签名、注解内容、参数等信息。
@Around("pt()")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行切点方法
Object result = pjp.proceed();
// 执行时长
Long runTime = System.currentTimeMillis() - beginTime;
// 记录日志
handleLog(pjp, runTime);
return result;
}
在 handleLog
方法中,我们可以进一步处理日志信息。通过 ProceedingJoinPoint
对象的 getSignature()
方法,我们可以获取方法的签名,进而获取注解内容。
private void handleLog(ProceedingJoinPoint pjp, Long runTime) {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
// 获取注解内容
Log logAnnotation = method.getAnnotation(Log.class);
// 获取模块
String title = logAnnotation.title();
// 获取业务类型
BusinessType businessType = logAnnotation.businessType();
// ...
}
除了获取注解内容外,我们还可以通过 HttpServletRequest
对象获取请求的方法、URL、IP地址等信息。
@Autowired
HttpServletRequest httpServletRequest;
// ...
private void handleLog(ProceedingJoinPoint pjp, Long runTime) {
// ...
// 请求方法
String httpMethod = httpServletRequest.getMethod();
// IP地址
String ip = IPUtils.getIpAddr(httpServletRequest);
// 请求URL
StringBuffer requestURL = httpServletRequest.getRequestURL();
// ...
}
最后,在 handleLog
方法中,我们可以根据需求对日志进行进一步处理,比如将日志存储到数据库或者输出到控制台。
private void handleLog(ProceedingJoinPoint pjp, Long runTime) {
// ...
// 封装日志对象
SysLog sysLog = new SysLog(title, businessType, httpMethod, requestURL.toString(), ip, params, runTime);
// 这里就是将日志对象输出了,你可以根据需求,把它存到数据库
// 我这里就简单地打印出来啦!
System.out.println(sysLog);
}
日志处理的使用用例:
@Log(title = "测试日志模块", businessType = BusinessType.OTHER)
@PostMapping("demo")
public R<TestEntity> demo(@RequestBody TestEntity testEntity) throws InterruptedException {
return R.ok(testEntity);
}
在这个例子中,我们在 demo
方法上添加了 @Log
注解。其中,title
参数表示日志模块的名称,businessType
参数表示业务类型。通过这样的配置,我们可以在方法执行前后自动记录日志信息。
当请求到达 /demo
接口时,切面会拦截到该方法的执行,并根据注解的配置进行日志记录。在执行完方法后,我们可以获取到请求的方法、URL、IP地址等信息,并且可以根据 @Log
注解的内容进行进一步的日志处理。
完整代码:
@Aspect
@Component
public class LogAspect {
@Autowired
HttpServletRequest httpServletRequest;
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/**
* 定义切面
*/
@Pointcut("@annotation(com.xiaoke.annotation.Log)")
public void pt() {
}
/**
* 环绕切点
* @param pjp join point for advice
* @return result
* @throws Throwable throws IllegalArgumentException
*/
@Around("pt()")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行切点方法
Object result = pjp.proceed();
// 执行时长
Long runTime = System.currentTimeMillis() - beginTime;
// 记录日志
handleLog(pjp,runTime);
return result;
}
private void handleLog(ProceedingJoinPoint pjp,Long runTime) {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
// 获取注解内容
Log logAnnotation = method.getAnnotation(Log.class);
// 获取模块
String title = logAnnotation.title();
// 获取业务类型
BusinessType businessType = logAnnotation.businessType();
Object[] args = pjp.getArgs();
// 参数
String params = JSON.toJSONString(args);
// 请求方法
String httpMenthod = httpServletRequest.getMethod();
// ip
String ip = IPUtils.getIpAddr(httpServletRequest);
// 请求url
StringBuffer requestURL = httpServletRequest.getRequestURL();
// 封装日志对象
SysLog sysLog = new SysLog(title, businessType, httpMenthod, requestURL.toString(), ip, params, runTime);
// 这里就是将日志对象输出了,你可以根据需求,把它存到数据库
// 我这里就简单地打印出来啦!
System.out.println(sysLog);
}
}
视频教程:哔哩哔哩
评论区