• 一文教你如何在项目开发中使用日志


    SpringBoot日志

    日志框架介绍

    日志框架:

    1. JUL:java原生日志框架
    2. log4j:已终止
    3. logback:原作者在log4j的基础上改进
    4. log4j2:在logback基础上改进,,有自己独立的门面

    日志门面:

    image-20220806102737178

    slf4j:日志门面,日志的抽象层,一层规范,日志框架按照其规范实现具体细节即可,使用时,直接通过操作门面的方式去使用日志

    阿里规范:

    应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API。使用门面模式的日志框架,有利于维护和各个类的日志处理方法统一。

    实际使用:

    实际项目开发中,遵循阿里规范,使用SLF4J和其他日志框架相结合的方式。

    SLF4J绑定其他日志所需依赖:

    绑定流程:

    1. 添加slf4j-api的依赖

    2. 使用slf4j的API在项目中进行统一的日志记录

    3. 绑定具体的日志实现框架

      a. 绑定已经实现了slf4j的日志框架,直接添加对应依赖

      b. 绑定没有实现slf4j的日志框架,先添加日志的适配器,再添加实现类的依赖

    4. slf4j有且仅有一个日志实现框架的绑定(如果出现多个默认使用第一个依赖日志实现)

    绑定jul日志:

    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-apiartifactId>
        <version>1.7.27version>
    dependency>
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-jdk14artifactId>
        <version>1.7.25version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    绑定log4j的实现:

    
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-apiartifactId>
        <version>1.7.27version>
    dependency>
    
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-log4j12artifactId>
        <version>1.7.27version>
    dependency>
    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    绑定log4j2:

    <!--使用slf4j作为日志的门面,使用log4j2来记录日志 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.30</version>
    </dependency>
    <!--为slf4j绑定日志实现 log4j2的适配器 -->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.12.1</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 绑定logback

      <!--使用slf4j作为日志的门面,使用log4j2来记录日志 -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.30</version>
      </dependency>
      <!--为slf4j绑定日志实现 logback的适配器 -->
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.2.3</version>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

    SLF4J原理解析

    参考文章:Java日志框架:slf4j作用及其实现原理 - 五月的仓颉 - 博客园 (cnblogs.com)

    SLF4J是一个日志规范,其他日志框架根据其规范具体实现即可,外部调用时,直接操作SLF4j。

    一般的Java项目而言,日志框架 会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。

    具体桥接可以参考下方文章:文档合集 (ydlclass.com)

    查看SpringBoot的默认实现:

    SpringBoot的starter依赖中,包含了spring-boot-starter-logging依赖,该依赖中指定logback为默认的依赖。

    image-20220806104635200

    依赖详情:

    image-20220806104740658

    springboot默认以logback为依赖,logback-classic是log4j的一个改良版本,同时它完整实现了slf4j API,其余两个依赖为日志框架桥接,也就是说如果你的项目中或引的第三方jar包中有使用了log4j或者jul作为日志框架,则使用slf4j的实现。

    image-20220806105435700

    原理解析:

    1. SLF4J通过LoggerFactory加载日志具体的实现对象。
    2. LoggerFactory在初始化的过程中,会通过performInitialization()方法绑定具体的日志实现。
    3. 在绑定具体实现的时候,通过类加载器,加载org/slf4j/impl/StaticLoggerBinder.class
    4. 所以,只要是一个日志实现框架,在org.slf4j.impl包中提供一个自己的StaticLoggerBinder类,在其中提供具体日志实现的LoggerFactory就可以被SLF4J所加载

    进入 LoggerFactory

    在slf4j中创建logger的方法是:

    image-20220806105747968

    getIloggerFactory()中的performInitialization方法绑定具体的日志

    image-20220806105849840

    image-20220806105922259

    查看bing方法,在绑定具体实现的时候,通过类加载器,加载org/slf4j/impl/StaticLoggerBinder.class

    image-20220806110514373

    查看具体实现:

    image-20220806110741388

    所以,只要是一个日志实现框架,在org.slf4j.impl包中提供一个自己的StaticLoggerBinder类,在其中提供具体日志实现的LoggerFactory就可以被SLF4J所加载

    切换SpringBoot默认依赖

    SpringBoot默认的logback日志已经非常满足我们的使用了,我们在这里只介绍一下切换方法。

    参考文章:(95条消息) spring boot 项目中使用log4j打印日志到Redis(详解)_至尊灬宝er的博客-CSDN博客_log4j redis

    lomback日志的使用

    基本使用

    他是springboot的默认日志依赖,因此我们不需要再引入依赖,直接使用即可。

        private final static Logger logger = LoggerFactory.getLogger(AppController.class);
        logger.info("我是日志");
    
    • 1
    • 2

    问题:需要打印日志的类,都需要添加该方法,麻烦,推荐使用Lombok的@SLF4J注解,来默认生成上方代码。

    依赖:

            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.16version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用方式:

    image-20220806142804429

    效果:

    image-20220809095347481

    此时,当我们查询mysql时,发现数据库没有打印日志,需要开启。

    # 控制台打印sql日志
    logging.level.com.cache.mycache.dao=debug
    
    • 1
    • 2

    logging.level+mapper文件所在路径

    image-20220809095437337

    效果:

    image-20220809095522216

    logback的yaml配置详情:(93条消息) Spring Boot 默认日志使用__星辰夜风的博客-CSDN博客_spring 默认log

    通过配置文件配置logback

    yaml中配置logback的配置文件路径

    logging:
      config: classpath:logback/logback-${spring.profiles.active}.xml
    
    • 1
    • 2

    image-20220809100945214

    不同环境下,对日志的打印要求不一样,因此可以通过文件进行控制。

    配置简单:logback的使用和logback.xml详解 - 行走在云端的愚公 - 博客园 (cnblogs.com)

    详细配置:(92条消息) 使用logback输出日志总结_MrYuShiwen的博客-CSDN博客_logback打印日志

    配置文件详情:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="30 seconds" debug="false">
        <contextName>SMPE-ADMIN</contextName>
        <property name="LOG_HOME" value="logs/%d{yyyy-MM,aux}/"/>
        <property name="LOG_" value="logs/"/>
        <property name="log.charset" value="utf-8"/>
        <property name="log.pattern"
                  value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
        <!--输出到控制台-->
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>${log.pattern}</pattern>
                <charset>${log.charset}</charset>
            </encoder>
        </appender>
    
        <!-- 按照每天生成日志文件 -->
        <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd-HH}.log</FileNamePattern>
                <MaxHistory>60</MaxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>${log.pattern}</pattern>
                <charset>${log.charset}</charset>
            </encoder>
        </appender>
    
        <!--普通日志输出到控制台-->
        <root level="info">
            <!-- 开发环境日志只输出到控制台,不输出到文件 -->
            <appender-ref ref="console"/>
        </root>
    </configuration>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    效果:image-20220809104723172

    Mysql日志

    目的:进行数据库查询时,打印sql语句,并能打印sql操作结果。

    sql日志

    在控制台打印Mybatis日志

    # 控制台打印sql日志
    logging.level.com.cache.mycache.dao=debug
    
    • 1
    • 2

    效果:

    image-20220630142246152

    输出的是dao层的日志

    image-20220630142321953

    log4jdbc

    log4jdbc 是一个 Java JDBC Driver,可以记录 SQL 日志和 SQL 执行时间等信息

    效果:

    image-20220809110247042

    详细配置参考文章:(107条消息) Java - log4jdbc 使用与原理介绍(SQL/日志监控)_pan_mlpan的博客-CSDN博客_jdbc sql 监控

    1. 安装依赖

    <dependency>
          <groupId>org.bgee.log4jdbc-log4j2groupId>
          <artifactId>log4jdbc-log4j2-jdbc4.1artifactId>
          <version>1.16version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 配置

    在使用 log4jdbc 时,需要进行三个配置:

    • 更改数据库连接信息
    • 编写 log4jdbc.log4j2.properties 文件
    • 配置 logger
    1. 更改数据库连接
      1. url 加上前缀 jdbc:log4jdbc
      2. driverClassName 改为 net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    # 修改前
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/ops_platform?characterEncoding=utf-8&useSSL=false
    
    # 修改后
    spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/ops_platform?characterEncoding=utf-8&useSSL=false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 编写 log4jdbc.log4j2.properties 文件

      1. 在resource目录下创建log4jdbc.log4j2.properties

      2. 内容

        # If you use SLF4J. First, you need to tell log4jdbc-log4j2 that you want to use the SLF4J logger
        log4jdbc.debug.stack.prefix=mycache
        log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
        log4jdbc.auto.load.popular.drivers=false
        log4jdbc.drivers=com.mysql.jdbc.Driver
        # 当该值为 false 时,boolean 值显示为 0 和 1 ,为 true 时 boolean 值显示为 true 和 false
        log4jdbc.dump.booleanastruefalse=true
        # 是否在 SQL 的行末添加一个分号
        log4jdbc.dump.sql.addsemicolon=true
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
    2. 编写logback.xml文件

      1. image-20220630144709283

      2. 在配置文件中执行logback.xml文件路径

        logging.config=classpath:logback.xml
        
        • 1
      3. 在resource的相应目录下创建文件

        
        <configuration scan="true" scanPeriod="30 seconds" debug="false">
            <contextName>BLOGcontextName>
            <property name="LOG_HOME" value="logs/%d{yyyy-MM,aux}/"/>
            <property name="LOG_" value="logs/"/>
            <property name="log.charset" value="utf-8"/>
            <property name="log.pattern"
                      value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)"/>
            
            <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
                <encoder>
                    <pattern>${log.pattern}pattern>
                    <charset>${log.charset}charset>
                encoder>
            appender>
        
            
            <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd-HH}.logFileNamePattern>
                    <MaxHistory>60MaxHistory>
                rollingPolicy>
                <encoder>
                    <pattern>${log.pattern}pattern>
                    <charset>${log.charset}charset>
                encoder>
            appender>
        
            
            
            <logger name="jdbc.resultsettable" level="INFO" additivity="false">
                <appender-ref ref="console"/>
            logger>
            
            <logger name="jdbc.sqltiming" level="INFO" additivity="false">
                <appender-ref ref="console"/>
            logger>
            
            <logger name="jdbc.sqlonly" level="OFF" additivity="false">
                <appender-ref ref="console"/>
            logger>
            
            <logger name="jdbc.resultset" level="ERROR" additivity="false">
                <appender-ref ref="console"/>
            logger>
            
            <logger name="jdbc.connection" level="OFF" additivity="false">
                <appender-ref ref="console"/>
            logger>
            
            <logger name="jdbc.audit" level="OFF" additivity="false">
                <appender-ref ref="console"/>
            logger>
        
            
            <root level="info">
                <appender-ref ref="console"/>
                <appender-ref ref="file"/>
            root>
        configuration>
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61

    附:也可以根据不同的环境,配置日志不同的输出格式。

    image-20220630144820215

    image-20220630144913863

    效果

    有数据库的查询语句和结果。

    image-20220630144558066

  • 相关阅读:
    基于单片机的恒流开关电源 BUCK电路设计
    买阿里云服务器,实操搭建nginx+php+mysql+thinkphp5全过程(5)
    ResNet网络架构
    CSS 面试题及答案
    golang用字符串数据生成http的pcap文件
    【ICer的脚本练习】通过perl脚本来检查仿真log的结果
    计算机系统(12)----- 处理机调度
    哈佛结构和冯诺依曼结构
    【gitlab】本地项目上传gitlab
    【c++刷题Day2】专题2线性DP
  • 原文地址:https://blog.csdn.net/zhang19903848257/article/details/126243865