从 Log4j 爆出漏洞以来,我们的日志框架就切换到了 Logback,毕竟出自同一个创始人之手,大部分的配置很相似,那么下面简单介绍下 Logback 和 Spring 进行集成时的配置;

Logback 依赖配置

<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-classic</artifactId>
	<version>1.2.11</version>
</dependency>

<dependency>
	<groupId>org.logback-extensions</groupId>
	<artifactId>logback-ext-spring</artifactId>
	<version>0.1.5</version>
</dependency>

依赖添加完成后,那如何使用呢?Logback 的配置加载有两种方式,下面进行一一介绍。

方式一:web.xml 中配置

<context-param>
	<param-name>logbackConfigLocation</param-name>
	<param-value>classpath:conf-logback/${env}_logback.xml</param-value>
</context-param>
<listener>
	<listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class>
</listener>

可以通过 env 变量区分是开发环境还是正式环境。

方式二:spring 配置添加 bean

<bean id="logInitialization"
		  class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
	<property name="targetClass" value="ch.qos.logback.ext.spring.LogbackConfigurer" />
	<property name="targetMethod" value="initLogging" />
	<property name="arguments" value="classpath:conf-logback/${env}_logback.xml"/>
</bean>

稍微去查看源码的话,你会发现,最后都是调用的 LogbackConfigurerinitLogging 方法对 Logback 的配置进行加载。

/**
 * Initialize logback from the given file.
 *
 * @param location the location of the config file: either a "classpath:" location
 *                 (e.g. "classpath:logback.xml"), an absolute file URL
 *                 (e.g. "file:C:/logback.xml), or a plain absolute path in the file system
 *                 (e.g. "C:/logback.xml")
 * @throws java.io.FileNotFoundException if the location specifies an invalid file path
 * @throws ch.qos.logback.core.joran.spi.JoranException
 *                                       Thrown
 */
public static void initLogging(String location) throws FileNotFoundException, JoranException {
    String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(location);
    URL url = ResourceUtils.getURL(resolvedLocation);
    LoggerContext loggerContext = (LoggerContext)StaticLoggerBinder.getSingleton().getLoggerFactory();

    // in the current version logback automatically configures at startup the context, so we have to reset it
    loggerContext.reset();

    // reinitialize the logger context.  calling this method allows configuration through groovy or xml
    new ContextInitializer(loggerContext).configureByResource(url);
}

从上面两个方式的配置中,我们发现有 logbackConfigLocation 的配置项,这个是为了指定 Logback 的配置的相对路径,如果没有配置该项,则默认会在 resources 目录下。

Logback 日志配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <contextName>${app_name}</contextName>
    <property name="app_name" value="atmt"/>
    <property name="log_home" value="/data/atmt_log"/>
    <!-- 在控制台输出日志 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 每天备份日志,备份INFO以上级别,除去ERROR -->
    <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${log_home}/${app_name}/info/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>10GB</totalSizeCap>
        </rollingPolicy>
        <!--<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log_home}/${app_name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                 <maxFileSize>1KB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>10</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>-->
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
    </appender>
    <!--只接受error级别的日志-->
    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${log_home}/${app_name}/error/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>30</maxHistory>
            <totalSizeCap>10GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
            <charset>UTF-8</charset> <!-- 设置字符集 -->
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>
    <!-- 异步输出 -->
    <appender name="file_info_async" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>256</queueSize>
        <!-- 为了打印栈堆信息,获取文件和行号 -->
        <includeCallerData>true</includeCallerData>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="file_info"/>
    </appender>
    <appender name="file_error_async" class="ch.qos.logback.classic.AsyncAppender">
        <discardingThreshold>0</discardingThreshold>
        <queueSize>256</queueSize>
        <includeCallerData>true</includeCallerData>
        <appender-ref ref="file_error"/>
    </appender>

    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info_async"/>
        <appender-ref ref="file_error_async"/>
    </root>

    <logger name="com.controller" level="INFO" additivity="false">
        <appender-ref ref="console"/>
        <appender-ref ref="file_info_async"/>
        <appender-ref ref="file_error_async"/>
    </logger>

    <!-- 输出sql相关日志,不需要可删除;additivity:是否向上级loger传递打印信息,默认是true-->
    <logger name="org.apache.ibatis" level="INFO" additivity="false" />
    <logger name="org.mybatis.spring" level="INFO" additivity="false" />
    <logger name="com.github.miemiedev.mybatis.paginator" level="INFO" additivity="false" />

</configuration>

参考

https://blog.csdn.net/haidage/article/details/6794529

https://www.cnblogs.com/gavincoder/p/10091757.html

https://blog.csdn.net/yzy85/article/details/104993534

https://www.baeldung.com/logback