文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Boot 使用 AOP 记录日志

2024-12-03 10:16

关注

本文转载自微信公众号「武培轩」,作者武培轩 。转载本文请联系武培轩公众号。

在项目开发中经常,日志系统是必不可少的,特别是管理系统,对于重要的操作都会有操作日志,然而这个操作不需要我们在相应的方法中一个一个的去实现,这肯定是不合适的,这样的操作无疑是加大了开发量,而且不易维护,所以实际项目中总是利用AOP(Aspect Oriented Programming)即面向切面编程来记录系统中的操作日志。

下面就来介绍如何在 Spring Boot 中 使用 AOP 记录日志:

加入依赖

首先加入 AOP 依赖:

  1.  
  2.  org.springframework.boot 
  3.  spring-boot-starter-aop 
  4.  

 

创建日志注解类

创建一个日志注解类,这样就可以在需要记录日志的方法上加上注解就可以记录日志了,注解内容如下:

  1. @Target({ElementType.PARAMETER, ElementType.METHOD}) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. @Documented 
  4. public @interface AopLogger { 
  5.  
  6.     String describe() default ""

配置 AOP 切面

定义一个 AopLoggerAspect 切面类,用 @Aspect 声明该类为切面类。

  1. @Component 
  2. public class AopLoggerAspect { 
  3.     private final Logger logger = LoggerFactory.getLogger(this.getClass()); 
  4.  
  5.     @Pointcut("@annotation(com.wupx.aop.logger.annotation.AopLogger)"
  6.     public void aopLoggerAspect() { 
  7.     } 
  8.  
  9.      
  10.     @Around("aopLoggerAspect()"
  11.     public Object doAround(ProceedingJoinPoint point) { 
  12.         RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 
  13.         ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; 
  14.         HttpServletRequest request = servletRequestAttributes.getRequest(); 
  15.         Object result = null
  16.         long startTime = System.currentTimeMillis(); 
  17.         try { 
  18.             result = point.proceed(); 
  19.         } catch (Throwable throwable) { 
  20.             throwable.printStackTrace(); 
  21.             logger.error(throwable.getMessage()); 
  22.         } 
  23.         String describe = getAopLoggerDescribe(point); 
  24.         if (StringUtils.isBlank(describe)) { 
  25.             describe = "-"
  26.         } 
  27.         // 打印请求相关参数 
  28.         logger.info("========================================== Start =========================================="); 
  29.         logger.info("Describe       : {}", describe); 
  30.         // 打印请求 url 
  31.         logger.info("URL            : {}", request.getRequestURL()); 
  32.         logger.info("URI            : {}", request.getRequestURI()); 
  33.         // 打印 Http method 
  34.         logger.info("HTTP Method    : {}", request.getMethod()); 
  35.         // 打印调用 controller 的全路径以及执行方法 
  36.         logger.info("Class Method   : {}.{}", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); 
  37.         // 打印请求的 IP 
  38.         logger.info("IP             : {}", request.getRemoteAddr()); 
  39.         // 打印请求入参 
  40.         logger.info("Request Args   : {}", point.getArgs()); 
  41.         // 打印请求出参 
  42.         logger.info("Response Args  : {}", result); 
  43.         logger.info("Time Consuming : {} ms", System.currentTimeMillis() - startTime); 
  44.         logger.info("=========================================== End ==========================================="); 
  45.         return result; 
  46.     } 
  47.  
  48.      
  49.     public static String getAopLoggerDescribe(JoinPoint joinPoint) { 
  50.         MethodSignature signature = (MethodSignature) joinPoint.getSignature(); 
  51.         Method method = signature.getMethod(); 
  52.         AopLogger controllerLog = method.getAnnotation(AopLogger.class); 
  53.         return controllerLog.describe(); 
  54.     } 

其中 「@Pointcut」 是定义一个切点,后面跟随一个表达式,表达式可以定义为某个 package 下的方法,也可以是自定义注解等。

「@Around」 为在切入点前后织入代码,并且可以自由的控制何时执行切点。

测试

接下来编写 Controller 层来进行测试:

  1. @RestController 
  2. @RequestMapping("/user"
  3. public class UserController { 
  4.  
  5.     private final UserService userService; 
  6.  
  7.     public UserController(UserService userService) { 
  8.         this.userService = userService; 
  9.     } 
  10.  
  11.     @PostMapping 
  12.     @AopLogger(describe = "添加用户"
  13.     public String addUser(@RequestBody User user) { 
  14.         UserEntity userEntity = new UserEntity(); 
  15.         BeanUtils.copyProperties(user, userEntity); 
  16.         return userService.addUser(userEntity); 
  17.     } 

只需要在接口上填写 @AopLogger 就可以记录操作日志。

启动服务,通过 PostMan 请求 http://localhost:8080/user 接口,输出的日志如下所示:

可以看到把入参、出参以及接口信息都记录了下来,是不是很简单呢,只需要简单几步就可以实现 AOP 日志,大家可以自己实践下。

本文的完整代码在 https://github.com/wupeixuan/SpringBoot-Learn 的 aop-logger 目录下。

来源:武培轩内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯