Linux Note / 运维笔记

SpringBoot log4j2 不能引入参数问题

Einic Yeo · 12月26日 · 2021年 ·

系统环境:

  • JAVA JDK 版本: 1.8
  • SpingBoot版本: 2.5.7

参考地址:

示例地址:

一、问题描述

最近在使用 SpringBoot 框架时,尝试使用 Log4j2 替换了默认的日志框架 Logback,根据网上的说法,在 pom.xml 文件中添加如下配置即可:

<dependencies>

    <!-- SpringBoot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!--移除存在默认日志框架的 Logback 的 Longging 依赖包 -->
        <exclusions>
            <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>

</dependencies>

在之前使用 SpringBoot 2.x 默认的日志框架 Logback 的时候,可以配置 Logback 的 xml 文件中引用 SpringBoot 配置文件 application.yml 里面的参数,实现一个 Logback 模板,这样只需要实现一套日志模板,就可以应用在不同的项目里,根据项目配置的 SpringBoot 参数,实现日志自动配置。

在使用 Logback 框架时,我们可以在 Logback 配置文件中使用如下方式引入 SpringBoot 参数,比如引入 spring.application.name 参数的值,用法如下:

<springProperty scope="context" name="appName" source="spring.application.name" defaultValue="defaultName" />

但是切换为 Log4j2 后,这种方式就不好使了,于是心理想着,肯定有相关解决办法,不可能切换到 log4j2 后,这么 low!

二、问题分析

经过网上查找一番,发现并没有很好的解决办法版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!,网上文章千篇一律,最后抱着试试看的态度浏览了一遍 Log4j2 的官方文档,在浏览文档过程中,发现确实存在 Log4j2 引入 SpringBoot 配置文件参数的介绍,如下:

然后尝试使用这种方式,在 Log4j2 的 xml 配置文件中,添加了一行读取 SpringBoot 参数的配置,如下:

<Properties>
    <!--读取 SprigBoot 中的 spring.application.name 参数-->
    <property name="applicationName" value="${spring:spring.application.name}"/>
</Properties>

引入变量时只需要在前面添加一个 ${spring:参数名称},即可引入 SpringBoot 中的参数。

然后就开始启动测试,发现居然不生效! 于是乎就访问了 Log4j2 的 Github,发现存在一个 log4j-spring-boot 项目,进入了看下源码中的 SpringLookup 类,就知道该项目就是解决问题的关键,于是在原先的 pom.xml 中引入了这个项目,问题得到了解决。

三、解决问题

pom.xml 引入 log4j-spring-boot 依赖,解决 Log4j2 中引入 Spring 参数不生效问题,文件内容如下:

pom.xml

    <!-- SpringBoot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!--移除 Logback-->
        <exclusions>
            <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>
    <!-- Log4j SpringBoot |- 解决引入 SpringBoot 配置文件参数问题的依赖-->
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-spring-boot</artifactId>
    </dependency>

然后 Log4j2 配置文件中,引入 SpringBoot 的 spring.application.name 参数,配置文件内容如下:

log4j2-spring.xml

<configuration>

    <Properties>
        <!--读取 SprigBoot 中的 spring.application.name 参数-->
        <property name="applicationName" value="${spring:spring.application.name}"/>
    </Properties>
    
    ......(其它配置,略)

</configuration>

四、创建示例项目

这里创建一个测试的 SpringBoot 使用 Log4j2 日志框架的示例项目,方便大家有个全面了解。

4版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!.1 Maven 引入 Log4j2 依赖

在 Maven 的 pom.xml 文件中,引入 log4j2 相关依赖,内容如下:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.7</version>
    </parent>

    <groupId>club.infvie</groupId>
    <artifactId>springboot-log4j2-read-example</artifactId>
    <version>0.0.1</version>
    <name>springboot-log4j2-read-example</name>
    <description>springboot log4j2 example</description>

    <dependencies>
        <!-- SpringBoot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--移除 Logback-->
            <exclusions>
                <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>
        <!-- Log4j SpringBoot -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-spring-boot</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4.2 创建 SpringBoot 配置文件

创建 SpringBoot 配置文件 application.yml,在里面添加 spring.applicatio版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!n.name 参数,内容如下:

application.yml

spring:
  application:
    name: springboot-log4j2-example

4.3 创建 版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!Log4j2 配置文件

在 Log4j2 的 xml 配置文件 log4j2-spring.xml 中,添加一个引入 Sp版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!ringBoot 的 spring.application.name 参数配置,内容如下:

log4j2-spring.xml

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <Properties>
        <!-- ===== 读取 SprigBoot 参数 ===== -->
        <property name="applicationName" value="${spring:spring.application.name}"/>

        <!-- 配置日志文件、日志归档文件命名 -->
        <property name="FILE_PATH" value="/logs/${applicationName}.log"/>
        <property name="FILE_PATH_ARCHIVE" value="/logs/${applicationName}_%d{yyyy-MM-dd}.%i.log.gz"/>

        <!-- 配置日志输出模式 -->
        <property name="LOG_PATTERN_CONSOLE"
                  value="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx"/>
        <property name="LOG_PATTERN_FILE"
                  value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%15.15t] %-40.40c{1.}: %m%n%throwable"/>
    </Properties>

    <appenders>
        <!--CONSOLE-->
        <console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${applicationName}${LOG_PATTERN_CONSOLE}" charset="UTF-8"/>
        </console>

        <!--FILE-->
        <RollingFile name="file_info" fileName="${FILE_PATH}" filePattern="${FILE_PATH_ARCHIVE}">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN_FILE}" charset="UTF-8"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="100MB"/>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingFile>
    </appenders>

    <Loggers>
        <Root level="INFO" additivity="false" includeLocation="true">
            <!--控制台-->
            <AppenderRef ref="console"/>
            <!--文件-->
            <AppenderRef ref="file_info"/>
        </Root>
    </Loggers>

</configuration>

4.4 创建 SpringBoot 启动类

创建 SpringBoot 项目启动类,内容如下:

package club.infvie;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

4.5 启动项目测试日志文件的命名

进入项目所在磁盘的 /logs 目录中,可以看到新的日志文件生成,并且命名为 springboot-log4j2-example.log,说明 Log4j2 配置已经成功读取了 SpringBoot 的 spring.application.name 参数,配置有效。

推荐大家自身去试试,这样每次 Log4j2 读取 SpringBoot 参数,一个模板可以多个项目中通用。

0 条回应