项目demo地址:https://github.com/causeThenEffect/spring-learn/tree/master/logback-test

以前对日志打印不够重视,后面维护代码的时候才发现,没有日志在排查线上问题时候是多么痛的领悟。

估计一些新手小伙伴和我一样,容易犯以下两种错误:

1.想要输出日志的时候,直接system.out就输出了,后来才发现这种方式不方便日志追踪,如果日志打印的量很大的话,还会影响应用的执行效率。

2.log4j,slf4j,logback,jdklog,common-logging傻傻分不清

slf4j和common-logging定义了抽象的日志打印接口

package org.slf4j;

public interface Logger {
  String ROOT_LOGGER_NAME = "ROOT";

  String getName();

  boolean isTraceEnabled();

  void trace(String var1);

  void trace(String var1, Object var2);

  void trace(String var1, Object var2, Object var3);

  void trace(String var1, Object... var2);

  void trace(String var1, Throwable var2);

  boolean isTraceEnabled(Marker var1);

  void trace(Marker var1, String var2);

  void trace(Marker var1, String var2, Object var3);

  void trace(Marker var1, String var2, Object var3, Object var4);

  void trace(Marker var1, String var2, Object... var3);

  void trace(Marker var1, String var2, Throwable var3);

  boolean isDebugEnabled();

  void debug(String var1);

  void debug(String var1, Object var2);

  void debug(String var1, Object var2, Object var3);

  void debug(String var1, Object... var2);

  void debug(String var1, Throwable var2);

  boolean isDebugEnabled(Marker var1);

  void debug(Marker var1, String var2);

  void debug(Marker var1, String var2, Object var3);

  void debug(Marker var1, String var2, Object var3, Object var4);

  void debug(Marker var1, String var2, Object... var3);

  void debug(Marker var1, String var2, Throwable var3);

  boolean isInfoEnabled();

  void info(String var1);

  void info(String var1, Object var2);

  void info(String var1, Object var2, Object var3);

  void info(String var1, Object... var2);

  void info(String var1, Throwable var2);

  boolean isInfoEnabled(Marker var1);

  void info(Marker var1, String var2);

  void info(Marker var1, String var2, Object var3);

  void info(Marker var1, String var2, Object var3, Object var4);

  void info(Marker var1, String var2, Object... var3);

  void info(Marker var1, String var2, Throwable var3);

  boolean isWarnEnabled();

  void warn(String var1);

  void warn(String var1, Object var2);

  void warn(String var1, Object... var2);

  void warn(String var1, Object var2, Object var3);

  void warn(String var1, Throwable var2);

  boolean isWarnEnabled(Marker var1);

  void warn(Marker var1, String var2);

  void warn(Marker var1, String var2, Object var3);

  void warn(Marker var1, String var2, Object var3, Object var4);

  void warn(Marker var1, String var2, Object... var3);

  void warn(Marker var1, String var2, Throwable var3);

  boolean isErrorEnabled();

  void error(String var1);

  void error(String var1, Object var2);

  void error(String var1, Object var2, Object var3);

  void error(String var1, Object... var2);

  void error(String var1, Throwable var2);

  boolean isErrorEnabled(Marker var1);

  void error(Marker var1, String var2);

  void error(Marker var1, String var2, Object var3);

  void error(Marker var1, String var2, Object var3, Object var4);

  void error(Marker var1, String var2, Object... var3);

  void error(Marker var1, String var2, Throwable var3);
}

log4j实现了common-logging的抽象接口

logback实现了slf4j的抽象接口

这里体现了面向接口编程的思维方式,用到了门面模式

如何使用logback打印日志
在spring-boot项目的资源文件下添加配置文件logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>logback</contextName>
    <property name="log.path" value="./logs"/>
    <property name="CONSOLE_LOG_PATTERN"
              value="%red(%date{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %red([%thread]) %boldMagenta(%logger{50}) %cyan(%msg%n)"/>
    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
             <level>ERROR</level>
         </filter>-->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!--输出到文件-->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 过滤器,只记录WARN级别的日志 -->
        <!-- 果日志级别等于配置级别,过滤器会根据onMath 和 onMismatch接收或拒绝日志。 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 设置过滤级别 -->
            <level>DEBUG</level>
            <!-- 用于配置符合过滤条件的操作 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 用于配置不符合过滤条件的操作 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/logback.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>1MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--    root节点实际上是配置启用哪种appender,可以添加多个appender-->
    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

    <!-- logger节点可以指定具体包或类的日志配置 -->
    <!-- name属性为必选,指定要配置的包或类,level和additivity为可选,有缺省值 -->
    <!-- level表示日志级别,这里配置info级别,表示info及以上级别的日志被输出 -->
    <!-- additivity表示日志是否传递到上一级,默认为true -->
    <logger name="com.szp.logback.dao" level="DEBUG" additivity="false">
        <appender-ref ref="console"/>
    </logger>

</configuration>

在spring-boot中添加了这个配置文件,就可以精细化控制项目的日志输出

比如:

  1. 可以配置不同级别的日志输出到不同文件夹下面
  2. 控制不同目录的日志输出级别,就可以打印出mybatis的sql

这就是springboot自动化配置的优势,此配置文件就会被自动扫描,然后加载logback日志输出功能。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐