侧边栏壁纸
博主头像
学校乐园369博主等级

没有你学不会的,只会是你不想学

  • 累计撰写 8 篇文章
  • 累计创建 5 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SpringBoot AOP实现统一日志处理

xiaoke
2024-03-08 / 0 评论 / 0 点赞 / 3919 阅读 / 7151 字

在基于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);
    }
}

视频教程:哔哩哔哩

0

评论区