SpringBoot(四)-日志打印2

<@>是博客占位符,防止Jekyll不识别隔开

Log4j 2.x

  1. Log4j 2.x即是门面接口,也是实现

简单使用

  1. 右击23_Log,新建项目05_JCL_Log4j2.x
  2. 在pom.xml添加依赖

     <dependencies>
         <!-- 内部依赖门面log4j-api-->
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
             <version>2.13.3</version>
         </dependency>
     </dependencies>
    
  3. TestLog4j2类测试

     public class TestLog4j2 {
         public static void main(String[] args) {
             Logger logger = LogManager.getLogger(TestLog4j2.class);
             logger.fatal("致命_FATAL");
             logger.error("错误_ERROR");
             logger.warn("警告_WARN");
             logger.info("信息_INFO");
             logger.debug("调试_DEBUG");
             logger.trace("痕迹_TRACE");
         }
     }
    
  4. 直接运行即可,不需要配置文件,默认配置文件,可以看到,默认配置文件只打印ERROR级别以上的

     09:48:53.980 [main] FATAL com.zh.TestLog4j2 - 致命_FATAL
     09:48:53.988 [main] ERROR com.zh.TestLog4j2 - 错误_ERROR
    

配置文件

  1. resources下新建log4j2.xml
  2. 简单配置如下:

     <?xml version="1.0" encoding="UTF-8"?>
     <Configuration status="WARN">
         <!--抽取公共变量 -->
         <Properties>
             <Property name="PATTERN">%d{HH:mm:ss.SSS} [%-5p] %c{1.}: %m %n</Property>
             <Property name="CHARSET">UTF-8</Property>
             <Property name="BASE_PATH">F:/logs</Property>
             <Property name="BASE_NAME">log4j2</Property>
         </Properties>
        
         <Appenders>
             <Console name="Console">
                 <PatternLayout pattern="${PATTERN}"
                                charset="${CHARSET}"/>
             </Console>
         </Appenders>
         <!-- loggers -->
         <Loggers>
             <!-- 根logger -->
             <Root level="TRACE">
                 <AppenderRef ref="Console"/>
             </Root>
             <!-- 子logger -->
             <Logger name="com.zh" level="TRACE" additivity="false">
                 <AppenderRef ref="Console"/>
             </Logger>
         </Loggers>
     </Configuration>
    
  3. Configuration
    1. status: 控制Log4j内部日志的打印级别,比如status=”WARN”
      1. 就是前面几个打印日志开启内部日志的东西,内部日志级别大于WARN都会打印出来
    2. monitorInterval:每隔多少秒扫描配置文件、应用配置文件的最新修改,部署之后修改配置文件,能够隔一段时间再次扫描

       <?xml version="1.0" encoding="UTF-8"?>
       <Configuration status="WARN" monitorInterval="5">
       </Configuration>
      
  4. Console
    1. target:可以取值SYSTEM_OUT(默认值)、SYSTEM_ERR(打印出来红色)
     <Console name="Console" tartet="SYSTEM_ERR">
         <PatternLayout pattern="${PATTERN}" charset="${CHARSET}"/>
     </Console>
    
  5. 控制台彩色打印

     <!--抽取公共变量 -->
     <Properties>
         <Property name="CHARSET">UTF-8</Property>
         <!--设置彩色打印的格式-->
         <Property name="PATTERN" value="%style{<@>%d{HH:mm:ss.SSS}}{black}\
     [%highlight{<@>%t}] %highlight{<@>%-5p}\
     %style{<@>%c{1.}}{magenta}: %m%n"/>
         <Appenders>
             <Console name="Console">
                 <!--disableAnsi=false 开启彩色打印-->
                 <PatternLayout pattern="${PATTERN}" charset="${CHARSET}" disableAnsi="false"/>
             </Console>
         </Appenders>
     </Properties>
    

Filter

  1. 代码示例:

     <Console name="Console">
         <PatternLayout pattern="${PATTERN}"
                        charset="${CHARSET}" />
        <!--这里设置Filter-->
     </Console>
    

1.单个ThresholdFilter的Filter

<!-- 示例1:关闭大于等于达到WARN级别的日志 -->
<!-- 达到(onMatch)级别(level)时 关闭(DENY)
     没有达到(onMismatch)级别(level)时 接收(ACCEPT)
 -->
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="ACCEPT"/>

<!-- 示例2: 开启大于等于达到WARN级别的日志 -->
<!-- 达到(onMatch)级别(level)时 接收(ACCEPT)
     没有达到(onMismatch)级别(level)时 关闭(DENY)
 -->
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
  1. 同样支持Log4j 1.x中的:DenyAllFilter、LevelMatchFilter、LevelRangeFilter、StringMatchFilter

2.多个Filter组合(交集、并集)

<!--多个Filter交集、并集-->
<!-- 下面二者交集为[DEBUG,ERROR)-->
<Filters>
    <!-- 关闭 >= ERROR级别的日志 -->
    <!-- NEUTRAL:没有达到ERROR级别,交给下一个Filter -->
    <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
    
    <!--达到DEBUG,则接收,达不到,则关闭 -->
    <!-- 只会输出WARN\INFO\DEBUG级别 -->
    <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
  1. ACCEPT: 开启。会忽略后面的所有Filter
  2. DENY: 关闭。会忽略后面所有的Filter
  3. NEUTRAL: 中立。会传递给下一个Filter进行处理

3.LevelRangeFilter

<Filters>
    <!-- 只开启[DEBUG,WARN]级别的日志 -->
    <LevelRangeFilter minLevel="WARN" maxLevel="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
  1. 需要注意的是,Log4j 1.x中的LevelRangeFilter
  2. minLevel: 是填写最大级别
  3. maxLevel: 是填写最小级别

Appender

1.File

<File name="File" fileName="${BASE_PATH}/${BASE_NAME}_file.log">
    <PatternLayout pattern="${PATTERN}" charset="${CHARSET}"/>
</File>

2.RollingFile

  1. 官方网站
<RollingFile name="RollingFile"
                     fileName="${BASE_PATH}/${BASE_NAME}.log"
                     filePattern="${BASE_PATH}/%d{yyyy}/%d{MM}/%d{dd}/HH_mm_ss_%i.log.gz">
    <PatternLayout pattern="${PATTERN}" charset="${CHARSET}"/>
    <Policies>
        <!-- 基于时间的滚动策略:当时间跨度达到5秒钟就滚动 -->
        <!-- 时间单位取决于filePattern的最小时间单位(就是上面filePattern设置的最小时间单位,上面设置的最小单位为s) -->
        <TimeBasedTriggeringPolicy interval="5"/>

        <!-- 基于文件大小的滚动策略:当文件大小达到10KB时就滚动 -->
        <SizeBasedTriggeringPolicy size="10KB"/>
    </Policies>
    <!-- 设置%i的最大值,默认是7 -->
    <DefaultRolloverStrategy max="10"/>
</RollingFile>

3.Delete

  1. 官网网站
  2. 就是这个标签

     <!-- 设置%i的最大值,默认是7 -->
     <DefaultRolloverStrategy max="10"/>
    
  3. 当超过最大值的时候如何删除呢? 因此需要配置删除策略

     <!-- 设置%i的最大值,默认是7 -->
     <DefaultRolloverStrategy max="10">
         <!-- maxDepth:要访问目录的最大级别数,默认值1,代表仅访问basePath目录中的文件 -->
         <Delete basePath="${BASE_PATH}" maxDepth="10">
             <!-- IfFileName && IfLastModified -->
             <!-- 填写相对于basePath的相对路径 -->
             <IfFileName glob="*.log.gz"/>
             <!-- 文件的时间超过5s -->
             <IfLastModified age="5s">
                 <!-- IfAccumulatedFileSize || IfAccumulatedFileCount -->
                 <IfAny>
                     <IfAccumulatedFileSize exceeds="20KB"/>
                     <IfAccumulatedFileCount exceeds="10"/>
                 </IfAny>
             </IfLastModified>
         </Delete>
     </DefaultRolloverStrategy>
    

4. Async

  1. 可以将其他appender包装成Async

     <Async name="Async">
         <!--将RollingFile包装成Async-->
         <Appender-ref redf="RollingFile"/>
     </Async>
    

Loggers

<!-- loggers -->
<Loggers>
    <!-- 根logger -->
    <Root level="TRACE">
        <AppenderRef ref="Console"/>
    </Root>
    <!-- 子logger -->
    <Logger name="com.zh" level="TRACE" additivity="false">
        <AppenderRef ref="Console"/>
        <AppenderRef ref="Async"/>
    </Logger>
</Loggers>

SLF4J+Log4j 2.x

  1. 右击23_Log,新建项目06_SLF_Log4j2.x
  2. pom.xml添加依赖

     <dependencies>
    <!--        <dependency>-->
    <!--            <groupId>org.slf4j</groupId>-->
    <!--            <artifactId>slf4j-api</artifactId>-->
    <!--            <version>1.7.30</version>-->
    <!--        </dependency>-->
    
         <!-- 仅仅是log4j2的实现,并没有实现SFL接口,因此导入没用-->
    <!--        <dependency>-->
    <!--            <groupId>org.apache.logging.log4j</groupId>-->
    <!--            <artifactId>log4j-core</artifactId>-->
    <!--            <version>2.13.3</version>-->
    <!--        </dependency>-->
    
         <!-- SLF4J + Log4j2的适配包,内部已经依赖slf4j-api,因此不需要在导入slf4j-api了 -->
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-slf4j-impl</artifactId>
             <version>2.13.3</version>
         </dependency>
    
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
             <version>1.18.12</version>
         </dependency>
     </dependencies>
    
  3. resources中添加log4j2.xml

     <Configuration status="WARN">
         <Properties>
             <Property name="PATTERN">%d{HH:mm:ss.SSS} [%-5p] %c{1.}: %m %n</Property>
             <Property name="CHARSET">UTF-8</Property>
         </Properties>
        
         <Appenders>
             <Console name="Console">
                 <PatternLayout pattern="${PATTERN}" charset="${CHARSET}"/>
             </Console>
         </Appenders>
            
         <Loggers>
             <Root level="TRACE">
                 <AppenderRef ref="Console"/>
             </Root>
         </Loggers>
     </Configuration>
    
  4. TestSLF4J_Log4j2

     //com.zh.TestSLF4J_Log4j2
     @Slf4j
     public class TestSLF4J_Log4j2 {
         public static void main(String[] args) {
             log.error("错误_ERROR");
             log.warn("警告_WARN");
             log.info("信息_INFO");
             log.debug("调试_DEBUG");
             log.trace("痕迹_TRACE");
         }
     }
    

交错复杂的日志系统

  1. 在实际开发过程中,不同的库(项目)内部使用的日志系统不一定相同
    1. 当多个带有日志系统的项目混合在一起时,日志系统可能就会变得有点复杂,甚至产生冲突
  2. 具体解决方法(略)

SpringBoot集成日志框架

  1. 在SpringBoot中,日志框架的建议
    1. SLF4J+Logback
    2. SLF4+Log4j 2.x
  2. 官方参考 https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#boot-features-logging

SpringBoot集成Logback

  1. SpringBoot默认已经集成了Logback,不用再添加Logback的依赖,配置文件位置是
    1. classpath:logback.xml
    2. classpath: logback-spring.xml(SpringBoot推荐)
  2. SpringBoot内置的Lockback默认配置
    1. spring-boot.jar->org/springframework/boot/logging/logback/defaults.xml
  3. 项目举例:
    1. 右击22_spparent->新建一个Module为06_log
    2. 新建入口Application

       @SpringBootApplication
       public class Application48 {
           public static void main(String[] args) {
               SpringApplication.run(Application48.class, args);
           }
       }
      
    3. 新建LogController

       //com.zh.controller.LogController
       @RestController
       @Slf4j
       public class LogController {
           @GetMapping("/log")
           public String log() {
               //log就是默认SLF+logback
               log.info("info log-----");
               log.warn("warn log-----");
               return "log";
           }
       }
      
    4. 运行入口程序,浏览器访问http://localhost:8080/log,如下打印

       2021-08-03 21:24:45.140  INFO 21951 --- [nio-8080-exec-6] com.zh.controller.LogController          : info log-----
       2021-08-03 21:24:45.140  WARN 21951 --- [nio-8080-exec-6] com.zh.controller.LogController          : warn log-----
      
      1. 说明默认集成了logback,默认的配置可以通过查找项目依赖spring-boot.jar,然后找到org/springframework/boot/logging/logback/defaults.xml路径查看
  4. 如果不想使用默认的defaults.xml配置,也可以自定义配置
    1. 在resources下新建logback.xml,或者logback-spring.xml(SpringBoot推荐),内容如下

       <configuration>
           <!-- 抽取公共内容 -->
           <property name="PATTERN" value="%highlight([%-5p]) %red(%c{5}): %m%n"/>
           <property name="CHARSET" value="UTF-8"/>
              
           <!-- appender -->
           <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
               <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
                   <charset>${CHARSET}</charset>
                   <pattern>${PATTERN}</pattern>
               </encoder>
           </appender>
              
           <root level="WARN">
               <appender-ref ref="console"/>
           </root>
              
           <logger name="com.zh.controller" level="INFO" additivity="false">
               <appender-ref ref="console"/>
           </logger>
       </configuration>
      
    2. 重新运行项目,打印如下:

       [INFO ] c.z.c.LogController: info log-----
       [WARN ] c.z.c.LogController: warn log-----
      
  5. springboot默认的日志的级别是INFO,可以在项目的配置文件application.yml中做如下配置:

     # 修改springboot默认打印日志的级别
     logging:
       level:
         root: DEBUG
    

SpringBoot集成Log4j 2.x

  1. 配置文件位置是
    1. classpath:log4j2.xml
    2. classpath: log4j2-spring.xml(SpringBoot推荐)
  2. SpringBoot内置的Log4j 2.x默认配置
    1. spring-boot.jar->org/springframework/boot/logging/Log4j2/Log4j2.xml
  3. 项目举例
    1. 删除上面创建的logback-spring.xml
    2. 06_log的pom.xml添加依赖如下

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
           <exclusions>
               <!--去掉logging,剔除掉logback的实现-->
               <exclusion>
                   <groupId>org.springframework.boot</groupId>
                   <artifactId>spring-boot-starter-logging</artifactId>
               </exclusion>
           </exclusions>
       </dependency>
       <!--添加log4j2的starter-->
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-log4j2</artifactId>
       </dependency>
      
    3. 其他不变直接运行项目,发现打印日志正常,说明也有默认配置
    4. 自定义日志:resources下添加log4j2-spring.xml

       <Configuration status="WARN">
           <Properties>
               <Property name="PATTERN">[%-5p] %c: %m %n</Property>
               <Property name="CHARSET">UTF-8</Property>
           </Properties>
              
           <Appenders>
               <Console name="Console">
                   <PatternLayout pattern="${PATTERN}" charset="${CHARSET}"/>
               </Console>
           </Appenders>
                  
           <Loggers>
               <Root level="TRACE">
                   <AppenderRef ref="Console"/>
               </Root>
           </Loggers>
       </Configuration>
      

修改SpringBoot默认的日志配置

  1. 不做任何自定义日志配置文件,想修改默认的日志配置,可以在application.xml中修改
  2. 设置日志级别

     logging:
       level:
         # 配置rootlogger
         root: info
         # 配置子logger
         com.zh.service: debug
    
  3. 定义日志组

     logging:
       level:
         root: info
         # 定义一个变量级别
         project: debug
       # 定义一个组,这个组里面所有都用一个级别
       group:
         project:
           - com.zh.dao
           - com.zh.service
           - com.zh.controller
    
  4. 自定义配置文件的路径

     logging:
       config: calsspath: log4j2-spring.xml
    
Table of Contents