Java

Java slf4j 日志框架

slf4j 全称 Simple Logging Facade for Java, 是日志框架的一种抽象, 那么也就是说 slf4j 是不能单独使用的必须要有其他实现日志框架来配合使用

slf4j只是一个日志标准,并不是日志系统的具体实现。理解这句话非常重要,slf4j只做两件事情:

  • 提供日志接口
  • 提供获取具体日志对象的方法

slf4j 门面依赖

<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.9</version>
</dependency>
 
implementation("org.slf4j:slf4j-api:2.0.9")
implementation("org.slf4j:slf4j-api:2.0.17")

注意一点, 因具体实现不同引的包也不同, 配置方式也不同!!

log4j 实现

slf4j与log4j整合导入的jar包为:

  • slf4j-api.jar
  • slf4j-log4j12.jar //读取 log4j.xml 或 log4j.properties
  • log4j.jar

不推荐

log4j2 实现

slf4j与log4j2整合导入的jar包为:

  • log4j-slf4j-impl.jar
  • log4j-api.jar
  • log4j-core.jar
<dependencies>
    <!-- SLF4J API -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    
    <!-- SLF4J到Log4j2的绑定 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j2-impl</artifactId>
        <version>2.20.0</version>
    </dependency>
    
    <!-- Log4j2核心 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.20.0</version>
    </dependency>
</dependencies>

logback 实现

slf4j与logback整合导入的jar包为:

  • slf4j-api.jar
  • logback-core.jar //读取 logback.xml
  • logback-classic.jar

maven 依赖

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.11</version>
</dependency>
<dependency>  
	<groupId>ch.qos.logback</groupId>  
	<artifactId>logback-core</artifactId>  
	<version>1.4.11</version>  
</dependency>
implementation("ch.qos.logback:logback-classic:1.5.16")  
implementation("ch.qos.logback:logback-core:1.5.16")

logback 自用 java 模版

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
   <!-- 日志格式 -->
   <property name="LOG_PATTERN"
           value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] %logger{50}::%M-%line:%msg%n" />
   <!-- Console 输出设置 -->
   <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <Pattern>${LOG_PATTERN}</Pattern>
         <charset>utf8</charset>
      </encoder>
   </appender>
   <appender name="INFO_FILE"
      class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/info.log</file>
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>INFO</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
      <!-- 按天来回滚,如果需要按小时来回滚,则设置为{yyyy-MM-dd_HH} -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      	<!-- 回滚文件名 -->
         <fileNamePattern>./logs/info-%d{yyyy-MM-dd}.log</fileNamePattern>
         <!-- 如果按天来回滚,则最大保存时间为maxHistory 天,maxHistory天之前的都将被清理掉 -->
         <maxHistory>60</maxHistory>
      </rollingPolicy>
 
      <encoder>
         <Pattern>${LOG_PATTERN}</Pattern>
         <charset>UTF-8</charset>
      </encoder>
   </appender>
 
   <appender name="WARN_FILE"
      class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/warn.log</file>
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>WARN</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
      <!-- 按天来回滚,如果需要按小时来回滚,则设置为{yyyy-MM-dd_HH} -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      	<!-- 回滚文件名 -->
         <fileNamePattern>./logs/warn-%d{yyyy-MM-dd}.log</fileNamePattern>
         <!-- 如果按天来回滚,则最大保存时间为maxHistory 天,maxHistory天之前的都将被清理掉 -->
         <maxHistory>90</maxHistory>
      </rollingPolicy>
      <encoder>
         <Pattern>${LOG_PATTERN}</Pattern>
         <charset>UTF-8</charset>
      </encoder>
   </appender>
   
   <appender name="ERROR_FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/error.log</file>
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
         <level>ERROR</level>
      </filter>
      <!-- 按天来回滚,如果需要按小时来回滚,则设置为{yyyy-MM-dd_HH} -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <fileNamePattern>./logs/error-%d{yyyy-MM-dd}.log</fileNamePattern>
         <!-- 如果按天来回滚,则最大保存时间为maxHistory天,maxHistory天之前的都将被清理掉 -->
         <maxHistory>120</maxHistory>
      </rollingPolicy>
 
      <!-- 日志输出格式 -->
      <encoder>
         <Pattern>${LOG_PATTERN}</Pattern>
      </encoder>
   </appender>
   <!-- 异步输出,异步的log片段必须在同步段后面,否则不起作用 -->
   <appender name="ASYNC_INFO_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
      <discardingThreshold>0</discardingThreshold>
      <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
      <queueSize>10000</queueSize>
      <!-- 添加附加的appender,最多只能添加一个 -->
      <appender-ref ref="INFO_FILE" />
   </appender>
   
      <appender name="ASYNC_WARN_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
      <discardingThreshold>0</discardingThreshold>
      <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
      <queueSize>10000</queueSize>
      <!-- 添加附加的appender,最多只能添加一个 -->
      <appender-ref ref="WARN_FILE" />
   </appender>
 
   <appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
      <discardingThreshold>0</discardingThreshold>
      <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
      <queueSize>10000</queueSize>
      <!-- 添加附加的appender,最多只能添加一个 -->
      <appender-ref ref="ERROR_FILE" />
   </appender>
   <root level="INFO">
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="ASYNC_INFO_FILE" />
      <appender-ref ref="ASYNC_WARN_FILE" />
      <appender-ref ref="ASYNC_ERROR_FILE" />
   </root>
</configuration>

logback 自用 spring-boot模版

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
   <!-- logback -->
   <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
   <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
   <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
   <!-- 彩色日志格式 -->
   <property name="CONSOLE_LOG_PATTERN"
           value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39})::%M-%L%clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
   <!-- Console 输出设置 -->
   <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <pattern>${CONSOLE_LOG_PATTERN}</pattern>
         <charset>utf8</charset>
      </encoder>
   </appender>
 
   <appender name="INFO_FILE"
      class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/info.log</file>
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>INFO</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
      <!-- 按天来回滚, 如果需要按小时来回滚, 则设置为{yyyy-MM-dd_HH} -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      	<!-- 回滚文件名 -->
         <fileNamePattern>./logs/info-%d{yyyy-MM-dd}.log</fileNamePattern>
         <!-- 如果按天来回滚, 则最大保存时间为maxHistory 天, maxHistory天之前的都将被清理掉 -->
         <maxHistory>60</maxHistory>
      </rollingPolicy>
      <!-- 日志输出格式 -->
      <encoder>
         <Pattern>%d -%-4r [%t] %-5p %c::%M-%L %m%n</Pattern>
         <charset>UTF-8</charset>
      </encoder>
   </appender>
 
   <appender name="WARN_FILE"
      class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/warn.log</file>
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>WARN</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <fileNamePattern>./logs/warn-%d{yyyy-MM-dd}.log</fileNamePattern>
         <maxHistory>90</maxHistory>
      </rollingPolicy>
      <encoder>
         <Pattern>%d -%-4r [%t] %-5p %c::%M-%L %m%n</Pattern>
         <charset>UTF-8</charset>
      </encoder>
   </appender>
   
   <appender name="ERROR_FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
      <file>./logs/error.log</file>
      <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
         <level>ERROR</level>
      </filter>
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <fileNamePattern>./logs/error-%d{yyyy-MM-dd}.log</fileNamePattern>
         <maxHistory>120</maxHistory>
      </rollingPolicy>
      <encoder>
         <Pattern>%d -%-4r [%t] %-5p %c::%M-%L %m%n</Pattern>
      </encoder>
   </appender>
 
   <!-- 异步输出, 异步的log片段必须在同步段后面, 否则不起作用 -->
   <appender name="ASYNC_INFO_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT, DEBUG, INFO级别的日志 -->
      <discardingThreshold>0</discardingThreshold>
      <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
      <queueSize>10000</queueSize>
      <!-- 添加附加的appender,最多只能添加一个 -->
      <appender-ref ref="INFO_FILE" />
   </appender>
   
      <appender name="ASYNC_WARN_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <discardingThreshold>0</discardingThreshold>
      <queueSize>10000</queueSize>
      <appender-ref ref="WARN_FILE" />
   </appender>
 
   <appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
      <discardingThreshold>0</discardingThreshold>
      <queueSize>10000</queueSize>
      <appender-ref ref="ERROR_FILE" />
   </appender>
 
   <root level="INFO">
   <!-- 用异步输出的 appender-->
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="ASYNC_INFO_FILE" />
      <appender-ref ref="ASYNC_WARN_FILE" />
      <appender-ref ref="ASYNC_ERROR_FILE" />
   </root>
 
    <!--监控sql日志输出 -->
    <logger name="jdbc.sqlonly" level="INFO" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="jdbc.resultset" level="ERROR" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="jdbc.resultsettable" level="OFF" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="jdbc.connection" level="OFF" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="jdbc.sqltiming" level="OFF" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
    <logger name="jdbc.audit" level="OFF" additivity="false">
        <appender-ref ref="CONSOLE" />
    </logger>
</configuration>

for android

logback-android

  1. In app/build.gradle, add the following dependencies:
dependencies {
  compile 'org.slf4j:slf4j-api:1.7.25'
  compile 'com.github.tony19:logback-android:2.0.0'
}
  1. Create app/src/main/assets/logback.xml

自定义日志 Appender

logback的自定义,都是基于一个基类appender来实现。本身logback提供了AppenderBase和UnsynchronizedAppenderBase两个抽象类(同步和非同步)

start方法:初始时调用。故在编写如数据库入库,连接缓存或者mq时,可以在这个方法里面进行初始化操作。 stop:当停止时,调用。可做些资源释放操作。

SpringBoot | 第二十五章:日志管理之自定义Appender

package org.yang.agenta.log;
import ch.qos.logback.core.AppenderBase;
public class MyLogAppender extends AppenderBase {
 
    @Override
    protected void append(Object eventObject) {
        System.out.println("自定义输出=== " + eventObject);
    }
}
<!-- 自定义输出 -->
<property name="CUST_LOG_PATTERN" value="%d -%-4r [%t] %-5p %c-%L: %m%n" />
<!-- CUST 输出设置 -->
<appender name="CUST" class="org.yang.agenta.log.MyLogAppender">
    <encoder>
        <pattern>${CUST_LOG_PATTERN}</pattern>
        <charset>utf8</charset>
    </encoder>
</appender>
 

Junit

注解

@Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试 @ParameterizedTest :表示方法是参数化测试 @RepeatedTest :表示方法可重复执行,下方会有详细介绍 @DisplayName :为测试类或者测试方法设置展示名称 @BeforeEach :表示在每个单元测试之前执行 @AfterEach :表示在每个单元测试之后执行 @BeforeAll :表示在所有单元测试之前执行(需要将测试方法设置为statis) @AfterAll :表示在所有单元测试之后执行(需要将测试方法设置为statis) @Tag :表示单元测试类别,类似于JUnit4中的@Categories @Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore @Timeout :表示测试方法运行如果超过了指定时间将会返回错误 @ExtendWith :为测试类或测试方法提供扩展类引用