Spring Boot日志和AOP注解

Spring Boot日志

集成logback需要添加spring-boot-starter-logging依赖,而此依赖已经在spring-boot-starter中默认集成了,所以不用再添加此依赖了。默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台

logging常用配置

在这里插入图片描述
默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要将日志写入文件,则需在application.properties中设置logging.file或logging.path属性。logging.file,设置日志文件,可以是绝对路径,也可以是相对路径。logging.path,设置日志所在的目录,会在该目录下创建spring.log文件,并写入日志内容。注意:二者不能同时使用,如若同时使用,则只有logging.file生效

默认情况下,日志文件的大小达到10MB时会切分一次,产生新的日志文件, 如果要修改大小可以通过logging.file.max-size来配置,单位为MB,logback默认的日志级别为INFO,如果需要修改可以通过配置logging.level.包语法来配置, 包即可以是一个包名也支持全限定路径包.类,如logging.level.com.example.demo.dao=DEBUG, logging.level.包属性可以配置多个,可以为每个包进行单独设置日志级别,这种方式能够控制每个包的输出日志级别, 也可以设置root的日志级别logging.level.root=INFO

多环境日志配置

在application.properties中配置公共的日志配置, 开发测试配置相应的值,生产配置相应的值,使用spring.profiles.active

自定义日志

在Spring Boot中可即可以通过在application.properties中配置日志,也可以使用传统的配置文件(logback.xml)的方式来配置, 在spring boot中配置文件名字既可以是logback.xml也可以是logback-spring.xml,Spring推荐使用已logback-spring.xml, 使用logback-spring.xml可以使用多环境日志输出springProfile,当然配置文件的名称也可以是自定义的,自定义的名称需要在application.properties中使用logging.config配置对应的名字,如:logging.config=classpath:logback-config.xml, 配置文件的位置放在src/main/resources下面
logback-spring.xml:
在这里插入图片描述
根节点configuration
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false
contextName:每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改,可以通过%contextName来引用日志上下文名称
property:用来定义变量值的标签,通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量

在这里插入图片描述
appender:用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。另一种常见的日志输出到文件,随着应用的运行时间越来越长,日志也会增长的越来越多,将他们输出到同一个文件并非一个好办法。RollingFileAppender用于切分文件日志

  • rollingPolicy class:
    • TimeBasedRollingPolicy 根据时间来分割日志文件,每天生成一个,这样可能某一天日志文件很大,某天日志文件会很小,每天的日志文件的大小不固定
    • SizeBasedTriggeringPolicy: 根据文件大小来分割,每达到maxFileSize就分割出来一个文件
    • SizeAndTimeBasedRollingPolicy: 同时按照每天和大小来分割日志文件, 这种方式pattern中必须包含%d和%i
  • fileNamePattern: 定义分隔的日志文件的名称规则
  • maxHistory:表示只保留最近N天的日志,以防止日志填满整个磁盘空间
  • totalSizeCap: 指定日志文件的上限大小,例如设置为1GB的话,那么到了这个值,就会删除旧的日志

在这里插入图片描述

  • root:用来指定最基础的日志输出级别,只有一个level属性,用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,可以包含零个或多个元素,标识这个appender将会添加到这个logger

  • logger:用来设置某一个包或者具体的某一个类的日志打印级别、以及指定appender

    • name:用来指定受此logger约束的某一个包或者具体的某一个类。
    • level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF;如果未设置此属性,那么当前logger将会继承上级的级别,所谓像上级传递就是是否使用root的配置
    • addtivity:是否向上级logger传递打印信息。默认是true

当使用mybatis时,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:

  • 第一种把 改成 这样就会打印sql,不过这样日志那边会出现很多其他消息。
  • 第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
    在这里插入图片描述

AOP:面向切面编程

添加aop依赖

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

AOP的基本概念

切面(Advisor):表示从业务逻辑中分离出来的横切逻辑,比如性能监控,日志记录,权限控制等
连接点(JointPoint):程序执行过程中明确的点,一般是方法的调用
通知(Advice): 通知是切面的一种实现,可以完成简单的织入功能。通知定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是执行之后执行等。切入点定义切入的位置,通知定义切入的时间
切入点(PointCut): 就是带有通知的连接点,切入点指切面具体织入的方法
织入(Weaving): 织入是指将切面代码插入到目标对象的过程。代理的invoke方法完成的工作,可以称为织入
目标对象(Target): 目标对象指将要被增强的对象。即包含主业务逻辑的类的对象

实现AOP的切面主要有以下几个要素:

  • @Aspect: 将一个java类定义为切面类
  • @Pointcut: 定义一个切入点,可以是一个规则表达式
  • @Order(i): 当有多个切面满足条件时,需要定义切面的优先级,i值越小越先执行
  • @Before: 在切入点开始处切入内容
  • @After: 在切入点结尾处切入内容
  • @AfterReturning: 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
  • @Around: 在切入点前后切入内容,并自己控制何时执行切入点自身的内容
  • @AfterThrowing: 用来处理当切入内容部分抛出异常之后的处理逻辑

当同时有个多切面需要执行时,通过Order来定义优先级,值越小越优先执行。例如有两个切面,一个是记录请求@Order(1),一个是验证接口中的参数@Order(2),那么切面方法的执行顺序是先执行@Order(1)的before, 再执行@Order(2)的before; 然后再执行@Order(2)的@After或@AfterReturning,最后再执行@Order(1)的@After或@AfterReturning

示例

@Aspect
@Component
public class LoginAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //声明切入点
    @Pointcut("execution(public * com.example.demo.controller.*.*())")
    public void poincut(){}

    //定义前切切面
    @Before("poincut()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        logger.info("ip: " + request.getRemoteAddr());
        logger.info("url:" + request.getRequestURL().toString());
        logger.info("HTTP_METHOD:" + request.getMethod());
        //joinPoint.getSignature()获取切入点的相关信息
        logger.info("target: " + joinPoint.getSignature());
        logger.info("class_method:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("args:" + Arrays.toString(joinPoint.getArgs()));
    }

    //定义return切面
    @AfterReturning(pointcut = "poincut()", returning = "rep")
    public void doAfterReturn(Object rep){
        logger.info("rep: " + rep);
    }

}

控制台
在这里插入图片描述


转载
Spring Boot入门教程(六): 日志

猜你喜欢

转载自blog.csdn.net/lolwsyzc/article/details/83009481
今日推荐