springboot+@Aspect+@Log实现切面日志打印

在接口开发过程中,我们经常需要打印入参出参的log,来定位问题,比如:

logger.info("xx接口返回结果{}", JSON.toJSONString(result));

有时我们想要知道调用的ip地址,调用方法名等信息,那么这样一行代码就不能满足我们的要求。

基于springboot项目,我们可以使用@Aspect注解声明一个日志切面,在此切面中完成统一的返回日志打印或异常日志打印,下面详细介绍:

1.首先我们自定义一个注解Log,注解中可以定义一些属性,比如title接口注释

/**
 * 自定义操作日志记录注解
 *
 * @author china
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 接口注释
     */
    String title() default "";
}

2.在接口中使用@Log的注解来开启,注意注解只能作用在方法上

@Log(title = "切面测试接口")
@GetMapping()
 public String hello() {
     for (int i = 0; i < 10; i++) {
         String traceId = UUID.randomUUID().toString();
         log.info("请求打印traceId:" + traceId);
     }
     return "日志切面接口测试成功";
 }

3.接下来我们开始介绍@Aspect注解,首先介绍下相关注解

@Aspect:作用是把当前类标识为一个切面供容器读取
 
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 publicvoid型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice
@After: final增强,不管是抛出异常或者正常退出都会执行

下面贴出LogAspect代码,方法logPointCut定义了一个切点,注解@PointCut中@annotation(),括号中表示上述我们定义的@Log注解的位置,当然我们也可以使用切点表达式execution(),方法doAfterReturning和doAfterThrowing是正常返回和异常返回执行的方法。

/**
 * 系统日志切面
 */
@Aspect
@Component
public class LogAspect {
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    /**
     * 这里我们使用注解的形式
     * 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut("@annotation(com.demo.framework.aspectj.lang.annotation.Log)")
    public void logPointCut() {
    }

    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
        saveLog(joinPoint, null, jsonResult);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        saveLog(joinPoint, e, null);
    }
}

4.方法saveLog为业务逻辑方法,主要是解释如何获取需要打印的内容,如下:

/**
 * 保存日志
  */
 private void saveLog(JoinPoint joinPoint, final Exception e, Object jsonResult) {
     MethodSignature signature = (MethodSignature) joinPoint.getSignature();
     Method method = signature.getMethod();
     // 请求的地址
     String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
     LogBO sysLogBO = new LogBO();
     sysLogBO.setIp(ip);
     sysLogBO.setResult(JSON.toJSONString(jsonResult));
     SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     sysLogBO.setCreateDate(dateFormat.format(new Date()));
     Log sysLog = method.getAnnotation(Log.class);
     if (sysLog != null) {
         //注解上的描述
         sysLogBO.setRemark(sysLog.title());
     }
     //请求的 类名、方法名
     String className = joinPoint.getTarget().getClass().getName();
     String methodName = signature.getName();
     sysLogBO.setClassName(className);
     sysLogBO.setMethodName(methodName);
     //请求的参数
     Object[] args = joinPoint.getArgs();
     try {
         List<String> list = new ArrayList<String>();
         for (Object o : args) {
             list.add(JSON.toJSONString(o));
         }
         sysLogBO.setParams(list.toString());
     } catch (Exception ex) {
         // 记录本地异常日志
         log.error("异常信息:{}", ex.getMessage());
     }
     log.info("ip地址:{},创建时间:{},调用方法名:{},参数:{},返回值:{}",
             sysLogBO.getIp(), sysLogBO.getCreateDate(), sysLogBO.getMethodName(), sysLogBO.getParams(), sysLogBO.getResult());
 }

5.至此,代码部分结束,主要是介绍了使用@Aspect定义日志切面,最后贴出测试结果:
在这里插入图片描述参考文章:https://blog.csdn.net/zhuzhezhuzhe1

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中使用AspectJ进行面向切面编程是非常方便的。下面是一个简单的示例,演示了如何在Spring Boot应用程序中使用AspectJ。 首先,确保在你的Spring Boot项目中添加了AspectJ的依赖。你可以在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 接下来,创建一个切面类,这个类将包含你想要实现的横切关注点的逻辑。你可以使用`@Aspect`注解来标记这个类为一个切面类,并使用其他注解来定义切点和通知。 ```java import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore() { System.out.println("Before method execution"); } } ``` 在上面的示例中,`LoggingAspect`是一个切面类,使用了`@Aspect`和`@Component`注解进行标记。`logBefore()`方法是一个前置通知(Before Advice),它会在指定切点方法执行之前打印一条日志。 最后,在你的Spring Boot应用程序中启用AOP。在主应用程序类上添加`@EnableAspectJAutoProxy`注解。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 现在,当你运行Spring Boot应用程序时,切面类的逻辑将自动应用于指定的切点方法。在上面的示例中,`logBefore()`方法将在`com.example.demo.service`包中的所有方法执行之前被调用。 这只是一个简单的示例,你可以根据自己的需求使用更多的AspectJ注解和通知类型来实现更复杂的切面逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值