Apache log4j2 (一)

181 阅读9分钟

简述

这里简单讲述一下 java 简单程序和 springboot 集成 log4j2的用法,以及日志效果

版本

  • Log4j2 2.24.3
  • Java openjdk 21.0.7(以下配置使用 openjdk1.8.0也可以,亲测没啥问题)
  • Springboot——3.5.0(集成 log4j2 2.24.3)

java集成 log4j2、slf4j

效果
2025-05-28 17:30:03.421 Thread-1 ERROR com.fan.test.Case1.lambda$main$1(Case1.java:25) 这是日志 变量:error
2025-05-28 17:30:03.422 Thread-0 INFO  com.fan.test.Case1.lambda$main$0(Case1.java:12) 这是日志 变量:info
2025-05-28 17:30:03.423 Thread-0 ERROR com.fan.test.Case1.lambda$main$0(Case1.java:13) 这是日志 变量:error
2025-05-28 17:30:04.426 Thread-0 INFO  com.fan.test.Case1.lambda$main$0(Case1.java:12) 这是日志 变量:info
2025-05-28 17:30:04.426 Thread-0 ERROR com.fan.test.Case1.lambda$main$0(Case1.java:13) 这是日志 变量:error
2025-05-28 17:30:04.426 Thread-1 INFO  com.fan.test.Case1.lambda$main$1(Case1.java:24) 这是日志 变量:info
2025-05-28 17:30:04.426 Thread-1 ERROR com.fan.test.Case1.lambda$main$1(Case1.java:25) 这是日志 变量:error
2025-05-28 17:30:05.429 Thread-0 INFO  com.fan.test.Case1.lambda$main$0(Case1.java:12) 这是日志 变量:info
2025-05-28 17:30:05.430 Thread-0 ERROR com.fan.test.Case1.lambda$main$0(Case1.java:13) 这是日志 变量:error
2025-05-28 17:30:05.434 Thread-1 INFO  com.fan.test.Case1.lambda$main$1(Case1.java:24) 这是日志 变量:info
2025-05-28 17:30:05.435 Thread-1 ERROR com.fan.test.Case1.lambda$main$1(Case1.java:25) 这是日志 变量:error
目录结构
.
└── logs
    ├── 20250528
    │   ├── all-1.log.gz
    │   ├── all-2.log.gz
    │   ├── all-3.log.gz
    │   ├── error-1.log.gz
    │   ├── error-2.log.gz
    │   └── error-3.log.gz
    ├── all.log
    └── error.log
Demo
    package com.fan.test;
​
    import lombok.extern.slf4j.Slf4j;
​
​
    @Slf4j
    public class Case1 {
​
        public static void main(String[] args){
            Thread t = new Thread(() -> {
                while (true) {
                    log.info("这是日志 变量:{}", "info");
                    log.error("这是日志 变量:{}", "error");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
            t = new Thread(() -> {
                while (true) {
                    log.info("这是日志 变量:{}", "info");
                    log.error("这是日志 变量:{}", "error");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
        }
    }
​
依赖
<?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">
    <modelVersion>4.0.0</modelVersion>
​
    <groupId>com.fan.archetype</groupId>
    <artifactId>java-log4j2-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
​
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <log4j.version>2.24.3</log4j.version>
        <log4j-slf4j2-impl.version>2.24.3</log4j-slf4j2-impl.version>
        <slf4j-api.version>2.0.17</slf4j-api.version>
        <jackson-dataformat-yaml.version>2.19.0</jackson-dataformat-yaml.version>
        <jackson-databind.version>2.18.0</jackson-databind.version>
        <lombok.version>1.18.38</lombok.version>
    </properties>
​
    <dependencies>
        <!-- Log4j2核心依赖 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- slf4j日志门面 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-api.version}</version>
        </dependency>
        <!-- slf4j log4j2桥接器 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>${log4j-slf4j2-impl.version}</version>
        </dependency>
        <!-- 非必需 使用 yaml 格式 log4j2 配置需要加上这个依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>${jackson-dataformat-yaml.version}</version>
        </dependency>
        <!-- 非必需 如果Layout.type为 json 的话则需要加这个依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-databind.version}</version>
        </dependency>
        <!-- lombok 使用@Slf4j简化 logger 获取方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
    </dependencies>
</project>
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?><Configuration status="warn" strict="true">
​
    <Properties>
        <Property name="logDir">./logs</Property>
        <Property name="serviceName">log4j2</Property>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} %t %-5level %l %m%n</Property>
        <Property name="filePatternAll">${logDir}/%d{yyyyMMdd}/all-%i.log.gz</Property>
        <Property name="filePatternError">${logDir}/%d{yyyyMMdd}/error-%i.log.gz</Property>
    </Properties>
​
    <Appenders>
        <Appender type="CONSOLE" name="STDOUT">
            <Layout type="PatternLayout" pattern="${pattern}"/>
        </Appender>
        <Appender type="RollingFile" name="ALL" fileName="${logDir}/all.log" filePattern="${filePatternAll}">
            <Policies>
                <!--  modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动;
                      interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>;
                      maxRandomDelay需要滚动时可延迟 90 秒内-->
                <TimeBasedTriggeringPolicy modulate="true" interval="1" maxRandomDelay="90"/>
                <!--  文件体积到20MB时需要拆分 -->
                <SizeBasedTriggeringPolicy size="20MB"/>
            </Policies>
            <Layout type="PatternLayout" pattern="${pattern}"/>
            <DefaultRolloverStrategy>
                <Delete basePath="${logDir}" maxDepth="2">
                    <!-- 删除超过 366 天的文件 「天数:P数字D」「时间 PT数字+H或M或S」-->
                    <IfFileName glob="*/*gz" />
                    <IfLastModified age="P366D" />
                </Delete>
                <Delete basePath="${logDir}" maxDepth="1">
                    <!-- 删除文件后也需要删除目录 -->
                    <IfLastModified age="366d" />
                </Delete>
            </DefaultRolloverStrategy>
        </Appender>
        <Appender type="RollingFile" name="ERROR" fileName="${logDir}/error.log" filePattern="${filePatternError}">
            <Filters>
                <!--  仅接受 error 日志-->
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <Policies>
                <!--  一天滚动一次,以服务器时间为基准,需要滚动时可延迟 90 秒内-->
                <TimeBasedTriggeringPolicy modulate="true" interval="2" maxRandomDelay="90"/>
                <!--  文件体积到20MB时需要拆分 -->
                <SizeBasedTriggeringPolicy size="20MB"/>
            </Policies>
            <Layout type="PatternLayout" pattern="${pattern}"/>
            <DefaultRolloverStrategy>
                <Delete basePath="${logDir}" maxDepth="2">
                    <!-- 删除超过 366 天的文件 「天数:P数字D」「时间 PT数字+H或M或S」-->
                    <IfFileName glob="*/*gz" />
                    <IfLastModified age="366d" />
                </Delete>
                <Delete basePath="${logDir}" maxDepth="1">
                    <!-- 删除文件后也需要删除目录 -->
                    <IfLastModified age="366d" />
                </Delete>
            </DefaultRolloverStrategy>
        </Appender>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="ALL"/>
            <AppenderRef ref="ERROR"/>
        </Root>
    </Loggers>
</Configuration>
log4j2.yml
Configuration:
  status: warn
  strict: true
  properties:
    property:
      - name: logDir
        value: ./logs
      - name: serviceName
        value: log4j2
      - name: pattern
        value: "%d{yyyy-MM-dd HH:mm:ss.SSS} %t %-5level %l %m%n"
      - name: fileNameAll
        value: ${logDir}/all.log
      - name: filePatternAll
        value: ${logDir}/%d{yyyyMMdd}/all-%i.log.gz
      - name: fileNameError
        value: ${logDir}/error.log
      - name: filePatternError
        value: ${logDir}/%d{yyyyMMdd}/error-%i.log.gz
  Appenders:
    # 控制台 ===========================================
    Console:
      name: STDOUT
      PatternLayout:
        pattern: ${pattern}
    RollingFile:
      # rollingFile ALL ================================
      - name: ALL
        filename: ${fileNameAll}
        filePattern: ${filePatternAll}
        PatternLayout:
          pattern: ${pattern}
        Policies:
          #modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动;
          #interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>
          #maxRandomDelay需要滚动时可延迟 90 秒内
          TimeBasedTriggeringPolicy:
            maxRandomDelay: 90
            modulate: true
            interval: 1
          SizeBasedTriggeringPolicy:
            size: 50MB
        DefaultRolloverStrategy:
          Delete:
            - basePath: ${logDir}
              maxDepth: 2
              IfFileName:
                glob: "*/*gz"
              IfLastModified:
                age: P366D
            - basePath: ${logDir}
              maxDepth: 1
              IfLastModified:
                age: P366D
      # rollingFile ERROR ================================
      - name: ERROR
        filename: ${fileNameError}
        filePattern: ${filePatternError}
        PatternLayout:
          pattern: ${pattern}
        Policies:
          #modulate属性调整时间,true:0点为基准滚动,false:服务器启动时间开始滚动;
          #interval属性用来指定多久滚动一次,时间单位取决于<PatternLayout pattern>
          #maxRandomDelay需要滚动时可延迟 90 秒内
          TimeBasedTriggeringPolicy:
            maxRandomDelay: 90
            modulate: true
            interval: 1
          SizeBasedTriggeringPolicy:
            size: 50MB
        Filters:
          # 只接受 error 日志
          ThresholdFilter:
            level: ERROR
            onMatch: ACCEPT
            onMismatch: DENY
        DefaultRolloverStrategy:
          Delete:
            - basePath: ${logDir}
              maxDepth: 2
              IfFileName:
                glob: "*/*gz"
              IfLastModified:
                age: P366D
            - basePath: ${logDir}
              maxDepth: 1
              IfLastModified:
                age: P366D


  loggers:
    Root:
      level: info
      AppenderRef:
        - ref: STDOUT
        - ref: ALL
        - ref: ERROR
Log4j2配置解释,以 xml 为例

在 以下配置中,花括号{}中的属性必填,中括号[]中的属性非必填

<?xml version="1.0" encoding="UTF-8"?><Configuration {status} [strict]>
​
    <Properties>
        <Property {name}>value</Property>
    </Properties>
​
    <Appenders>
        <Appender {type|name} [fileName|filePattern]>
            <Layout {type} [pattern]/>
        </Appender>
        <!-- 另一种写法 节点直接用 type, 省略 type 属性-->
        <AppenderType {name} [fileName|filePattern]>
            <LayoutType .../>
            <TriggeringPolicy .../> 
        </Appender>
    </Appenders>
    <Loggers>
        <Logger {name|level} [additivity]>
            <AppenderRef {ref}/>
        </Logger>
        <Root {level}>
            <AppenderRef {ref}/>
        </Root>
    </Loggers>
</Configuration>
属性名描述值域
Configuration是整个 xml 配置文件的根节点「root element」
Configuration.statusLog4j2框架自身的日志等级,控制 Log4j2 框架自身的日志输出,并非控制用户(你)使用logger.info/error的输出,可用于排查日志打印出现异常时的情况error、warn、info、debug、trace
Configuration.strict是否严格校验XML格式,任何语法错误将导致配置加载失败true、false 默认为 false,建议true
PropertiesConfiguration下的子节点列表,Properties「属性列表,用法与 pom.xml的 properties 一样,可以不存在」
Property.name属性名,在其他地方引用:${property_name}
AppendersConfiguration下的Appender节点列表
AppenderAppenders列表的元素,控制日志内容的编排,可以控制对日志文件、日志目录的分割、压缩等
Appender.type表示Appender的类型,不同类型的Appender打印日志的方式不一样,如打印到控制台、打印到日志文件中常见的有【Console 控制台】【File非滚动配置文件,日志多时不建议使用】【RollingFile 滚动日志文件,避免文件过大,滚动的条件参考Appender 的子节点】 除此之外特殊场景【Async、Kafka、Socket 、JDBC 、SMTP, 后续再找时间补上】
Appender.name表示Appender的名称,在同一个配置文件中,Appender名唯一,不能有同名的两个Appender
Appender.fileName在Appender.type=RollingFile 或 File 时,需要指定日志文件路径文件路径,如./log/info.log
Appender.filePattern日志文件滚动路径的格式,当 Appender .type=RollingFile 时,需要指定这个滚动格式文件路径格式,如./log/%d{yyyyMMdd}/info-%i.log,%i 表示在同一个目录中文件的索引,达到指定条件后自动分割,从 1 开始递增
LayoutAppender下的子节点,控制每一行日志的格式
Layout.type日志编织的方式,常用PatternLayout,JsonLayoutPatternLayout,JsonLayout(输出 Json 格式日志方便 Elasticsearch检索),HtmlLayout,CsvLogEventLayout等。JsonLayout的默认格式:[ { "thread" : "main", "level" : "INFO", "loggerName" : "Case1", "message" : "Case1 info", "endOfBatch" : false, "loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger", "threadId" : 1, "instant" : { "epochSecond" : 1748332996, "nanoOfSecond" : 950540000 }, "threadPriority" : 5 }]
Layout.pattern日志编织的格式,仅适用于Layout.type=PatternLayoutPatternLayout的格式在下面
Layout.TriggeringPolicy文件的滚动「翻转」策略,常用:SizeBasedTriggeringPolicy,TimeBasedTriggeringPolicy,可同时使用多个策略,如按天滚动目录的同时,按照大小滚动同一天的文件【SizeBasedTriggeringPolicy文件大小达到指定体积后发生滚动,属性size,单位KB、MB、GB 或 TB,默认 10MB】,【TimeBasedTriggeringPolicy以时间为单位滚动,属性interval为时间,单位取决于Appender.filePattern中 %d 的最小单位,属性maxRandomDelay为时间范围,在该时间范围内滚动即可,避免服务器多个程序同时滚动增加负载,modulate="true"以服务器时间为基准滚动,fasle 表示以服务启动时间为基准】等等
Loggers是 Configuration 下的子节点,Logger 列表
RootLoggers下的子节点,表示所有logger的「祖先」
Root.level日志等级,控制你自己打印的日志输入,与 configuration.status不一样error、warn、info、debug、trace
LoggerLoggers下的子节点,可以不配置,若要对特殊的 logger 做处理可以在此配置。在常用的方式中「private static final Logger logger = LogManager.getLogger(Case1.class);」这里的 logger 名为Case1,每一个 logger 都有名字,与 Logger.name对应
Logger.name通过该属性与在 java类中的 logger 关联
Logger.level日志等级,控制指定 logger 的输出error、warn、info、debug、trace
Logger.additivity是否继承父Logger 。 Root 是所有 Logger 的祖先,若设置 true ,Logger 打印完之后 Root 也会打印一遍true、false,默认为 true,建议设置为 false,避免重复打印
AppenderRefRoot 或Logger的子节点,可以配置多个,表示 Appender 引用
AppenderRef.ref该属性的值=Appender.name 表示该 Logger 与该 Appender 关联,logger 可以按照该配置通过一个或多个规则打印日志

PatternLayout中的格式,可以参考源码中@ConverterKeys注解, 它定义了不同的格式类型

@ConverterKeys({ "C", "class" }) // %C %class 输出类名
@ConverterKeys({"d", "date"}) // 输出时间
@ConverterKeys({"enc", "encode"}) // %enc{%m}{HTML|XML|JSON|CRLF}将消息按照指定格式输出, 应用场景: 如有些消息字符串带有\n字符,直接输出的话会换行, 指定为XML格式的话, 文件直接输出\n字符. 说白了这个配置其实就是处理转义符的,或者不输出或者输出为字符串,几个格式的转义符有不同的处理方式
@ConverterKeys({ "endOfBatch" }) //TODO 输出一个true或false, 官网描述是日志事件的状态,暂时搞不懂啥意思
@ConverterKeys({ "equalsIgnoreCase" })
@ConverterKeys({ "equals" }) // 等于符合条件时替换字符串 %equals{参照对象}{等于某个值时}{替换为这个值}
@ConverterKeys({ "xEx", "xThrowable", "xException" }) // 打印异常栈 这个可以不写在配置文件中 log.info("message", Exception) 这样写也可以, 区别是在配置文件中可以指定位置, 不指定位置的话会在末尾输出
@ConverterKeys({ "d", "date" }) // 输出时间 %d{输出格式}
@ConverterKeys({ "F", "file" }) // 输出当前日志所在的文件
@ConverterKeys({ "l", "location" }) // 输出当前日志所在的具体位置
@ConverterKeys({ "i", "index" })//category="FileConverter" 作用于文件,文件滚动时的索引,如info-1.log,info-2.log
@ConverterKeys({ "L", "line" }) // 输出当前日志的位置所在对应文件的行数
@ConverterKeys({ "fqnc" }) // 输出当前Logger的完全限定类名 如org.apache.logging.log4j.spi.AbstractLogger
@ConverterKeys({ "c", "logger" }) // 打印logger名, LogManager.getLogger("name")为自定义名, LogManager.getLogger(Class<?> clazz)为类名
@ConverterKeys({ "marker" }) // 标记     private static final Marker marker = MarkerManager.getMarker("这是一个标记");          logger.error(marker,"Case1 error {}", "error"); 在pattern中用%marker可以输出标记
@ConverterKeys({ "X", "mdc", "MDC" })// 这个要和日志门面框架一起使用, MDC就是基于ThreadContext的实现,将key value存入线程上下文, 通过%mdc{key}打印出来
@ConverterKeys({ "m", "msg", "message" }) // 就是日志编织后的正文
@ConverterKeys({ "M", "method" }) // 日志输出所在的方法名
@ConverterKeys({ "N", "nano" }) // 输出纳秒
@ConverterKeys({ "pid", "processId" }) //输出进程号
@ConverterKeys({ "replace" }) // 替换 可做脱敏 %replace{源文本}{正则表达式}{替换表达式}
@ConverterKeys({ "r", "relative" }) //输出从 JVM 启动到创建日志事件所经过的毫秒数
@ConverterKeys({ "T", "tid", "threadId" }) // 输出线程号
@ConverterKeys({ "t", "tn", "thread", "threadName" })// 输出线程名
@ConverterKeys({ "tp", "threadPriority" }) //输出线程优先级
@ConverterKeys({ "ex", "throwable", "exception" }) // %ex、%throwable、%exception都表示输出异常

springboot3.5集成 log4j2、slf4j

麻烦的事情 springboot 都帮我们做完了,在依赖方面只需要剔除spring-boot-starter-logging,引用spring-boot-starter-log4j2即可,因为默认集成 logback,需要剔除。 log4j2的配置文件可以照搬上面的log4j2.xml或log4j2.yml

效果
2025-05-28 19:58:00.406 http-nio-9090-exec-2 ERROR com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:15) error
2025-05-28 19:58:00.408 http-nio-9090-exec-2 INFO  com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:16) info
2025-05-28 19:58:00.599 http-nio-9090-exec-3 ERROR com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:15) error
2025-05-28 19:58:00.601 http-nio-9090-exec-3 INFO  com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:16) info
2025-05-28 19:58:00.774 http-nio-9090-exec-4 ERROR com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:15) error
2025-05-28 19:58:00.774 http-nio-9090-exec-4 INFO  com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:16) info
2025-05-28 19:58:00.960 http-nio-9090-exec-5 ERROR com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:15) error
2025-05-28 19:58:00.960 http-nio-9090-exec-5 INFO  com.fan.archetype.springbootlog4j2.controller.Demo1.log1(Demo1.java:16) info
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.fan.archetype</groupId>
    <artifactId>springboot-log4j2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-log4j2</name>
    <description>springboot-log4j2</description>
​
    <properties>
        <java.version>21</java.version>
        <jackson-dataformat-yaml.version>2.19.0</jackson-dataformat-yaml.version>
        <lombok.version>1.18.38</lombok.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!-- 使用 log4j2.yaml -->
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>${jackson-dataformat-yaml.version}</version>
        </dependency>
        <!-- lombok 使用@Slf4j简化 logger 获取方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
    </dependencies>
​
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build></project>
application.yml
# 需要指定 log4j2配置文件
logging:
  file:
    name: log4j2.yml
Demo
package com.fan.archetype.springbootlog4j2.controller;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
@RequestMapping("/demo1")
@Slf4j
public class Demo1 {
​
    @GetMapping("/log1")
    public void log1(){
        log.error("error");
        log.info("info");
    }
}
​

本篇文章写的比较粗浅,时间有限,构想的文章框架还远未完成,只能算初稿,后续将会陆续完善~ 若您发现不对的地方欢迎指正 ^_^