• 【Java分享客栈】超简洁SpringBoot使用AOP统一日志管理纯干货干到便秘


    前言

    请问今天您便秘了吗?程序员坐久了真的会便秘哦,如果偶然点进了这篇小干货,就麻烦您喝杯水然后去趟厕所一边用左手托起对准嘘嘘,一边用右手滑动手机看完本篇吧。


    实现

    本篇AOP统一日志管理写法来源于国外知名开源框架JHipster的AOP日志管理方式

    1、引入依赖

    <!-- spring aop -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    

    2、定义logback配置

    1)、dev、test环境的spring-web包定义日志级别为INFO,项目包定义日志级别为DEBUG;
    2)、prod环境的spring-web包定义日志级别为ERROR,项目包定义日志级别为INFO;

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <include resource="org/springframework/boot/logging/logback/base.xml" />
        <logger name="org.springframework.web" level="INFO"/>
        <logger name="org.springboot.sample" level="TRACE" />
    
        <springProfile name="dev,test">
            <logger name="org.springframework.web" level="INFO"/>
            <logger name="org.springboot.sample" level="INFO" />
            <logger name="com.example.aoplog" level="DEBUG" />
        </springProfile>
    
        <springProfile name="prod">
            <logger name="org.springframework.web" level="ERROR"/>
            <logger name="org.springboot.sample" level="ERROR" />
            <logger name="com.example.aoplog" level="INFO" />
        </springProfile>
    
    </configuration>
    

    3、编写切面类

    1)、springBeanPointcut():单独定义的spring框架切入点;
    2)、applicationPackagePointcut():单独定义的项目包切入点;
    3)、logAfterThrowing():1和2定义的切入点抛出异常时日志格式及显示内容;
    4)、logAround():1和2定义的切入点方法进入和退出时日志格式及显示内容。

    package com.example.aoplog.logging;
    
    import com.example.aoplog.constants.GloablConstants;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.env.Environment;
    import org.springframework.core.env.Profiles;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    /**
     * <p>
     * AOP统一日志管理 切面类
     * </p>
     *
     * @author 福隆苑居士,公众号:【Java分享客栈】
     * @since 2022/5/5 21:57
     */
    @Aspect
    @Component
    public class LoggingAspect {
    
        private final Logger log = LoggerFactory.getLogger(this.getClass());
    
        private final Environment env;
    
        public LoggingAspect(Environment env) {
            this.env = env;
        }
    
        /**
        * 匹配spring框架的repositories、service、rest端点的切面
         */
        @Pointcut("within(@org.springframework.stereotype.Repository *)" +
            " || within(@org.springframework.stereotype.Service *)" +
            " || within(@org.springframework.web.bind.annotation.RestController *)")
        public void springBeanPointcut() {
            // 方法为空,因为这只是一个切入点,实现在通知中。
        }
    
        /**
        * 匹配我们自己项目的repositories、service、rest端点的切面
         */
        @Pointcut("within(com.example.aoplog.repository..*)"+
            " || within(com.example.aoplog.service..*)"+
            " || within(com.example.aoplog.controller..*)")
        public void applicationPackagePointcut() {
            // 方法为空,因为这只是一个切入点,实现在通知中。
        }
    
        /**
         * 记录方法抛出异常的通知
         *
         * @param joinPoint join point for advice
         * @param e exception
         */
        @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
        public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
    
           // 判断环境,dev、test or prod
            if (env.acceptsProfiles(Profiles.of(GloablConstants.SPRING_PROFILE_DEVELOPMENT, GloablConstants.SPRING_PROFILE_TEST))) {
                log.error("Exception in {}.{}() with cause = '{}' and exception = '{}'", joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
    
            } else {
                log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
            }
    
        }
    
        /**
         * 在方法进入和退出时记录日志的通知
         *
         * @param joinPoint join point for advice
         * @return result
         * @throws Throwable throws IllegalArgumentException
         */
        @Around("applicationPackagePointcut() && springBeanPointcut()")
        public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
            if (log.isDebugEnabled()) {
                log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
                    joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
            }
            try {
                Object result = joinPoint.proceed();
                if (log.isDebugEnabled()) {
                    log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
                        joinPoint.getSignature().getName(), result);
                }
                return result;
            } catch (IllegalArgumentException e) {
                log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
                    joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
    
                throw e;
            }
    
        }
    
    }
    

    4、测试

    1)、写个service

    package com.example.aoplog.service;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Service;
    
    /**
     * <p>
     * AOP统一日志管理测试服务
     * </p>
     *
     * @author 福隆苑居士,公众号:【Java分享客栈】
     * @since 2022/5/5 21:57
     */
    @Service
    @Slf4j
    public class AopLogService {
    
       public String test(Integer id) {
          return "传入的参数是:" + id;
       }
    }
    

    2)、写个controller

    package com.example.aoplog.controller;
    
    import com.example.aoplog.service.AopLogService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * <p>
     * 测试接口
     * </p>
     *
     * @author 福隆苑居士,公众号:【Java分享客栈】
     * @since 2022/4/30 11:43
     */
    @RestController
    @RequestMapping("/api")
    @Slf4j
    public class TestController {
    
       private final AopLogService aopLogService;
    
       public TestController(AopLogService aopLogService) {
          this.aopLogService = aopLogService;
       }
    
       @GetMapping("/test/{id}")
       public ResponseEntity<String> test(@PathVariable("id") Integer id) {
          return ResponseEntity.ok().body(aopLogService.test(id));
       }
    }
    

    3)、设置环境

    这里我试试dev,prod自己试听见没?不服一拳打哭你哦!

    server:
      port: 8888
    
    # 环境:dev-开发 test-测试 prod-生产
    spring:
      profiles:
        active: dev
    

    4)、效果

    不解释了自己看

    111.png

    试试异常情况,手动加个异常。

    @Service
    @Slf4j
    public class AopLogService {
    
       public String test(Integer id) {
          int i = 1/0;
          return "传入的参数是:" + id;
       }
    }
    

    效果

    222.png


    总结

    OK!打完收工!
    链接:https://pan.baidu.com/doc/share/flr0QYwZYPYxmWSRPbnJRw-1028798558141759
    提取码:bxaa


    记住,别点赞,别推荐,别关注 ,好好上个厕所喝杯水,你们今天下班前能拉出来我就心满意足了。


  • 相关阅读:
    java 日期的格式化
    JAVA 线程
    java 异常
    java 内部类
    java 多态
    SpringBoot(12) SpringBoot创建非web应用
    SpringCloud(1) 架构演进和基础知识简介
    SpringBoot(11) SpringBoot自定义拦截器
    SpringBoot(10) Servlet3.0的注解:自定义原生Servlet、自定义原生Listener
    SpringBoot(9) SpringBoot整合Mybaties
  • 原文地址:https://www.cnblogs.com/fulongyuanjushi/p/16227044.html
Copyright © 2020-2023  润新知