1. 概述

在本教程中,我们将展示如何修复警告 “log4j: WARN No Appender can be find for logger” 。我们将解释什么是附加程序以及如何定义它。此外,我们将展示如何以不同的方式解决警告。

2.Appender定义

我们首先解释一下什么是appender。 Log4j允许我们将日志放入多个目的地。 它打印输出的每个目的地称为追加器 。我们有用于控制台、文件、JMS、GUI 组件等的附加程序。

log4j 中没有定义默认的附加程序。 此外,记录器可以有多个追加器 在这种情况下,记录器将输出打印到所有这些追加器中。

3. 警告信息解释

现在我们知道什么是附加程序,让我们了解当前的问题。 警告消息表明无法找到记录器的附加程序。

让我们创建一个 NoAppenderExample 类来重现该警告:

public class NoAppenderExample {
    private final static Logger logger = Logger.getLogger(NoAppenderExample.class);

    public static void main(String[] args) {
        logger.info("Info log message");
    }
}

我们在没有任何 log4j 配置的情况下运行我们的类。之后,我们可以在控制台输出中看到警告以及更多详细信息:

log4j:WARN No appenders could be found for logger (com.baeldung.log4j.NoAppenderExample).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

4. 解决配置问题

默认情况下,Log4j 会在应用程序的资源中查找配置文件 ,该文件可以是 XML 或 Java 属性格式。现在让我们在 resources 目录下定义 log4j.xml 文件:

<log4j:configuration debug="false">
    <!--Console appender -->
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
        </layout>
    </appender>

    <root>
        <level value="DEBUG"/>
        <appender-ref ref="stdout"/>
    </root>
</log4j:configuration>

我们定义了 记录器,它位于记录器层次结构的顶部。所有应用程序记录器都是它的子级并覆盖它的配置。我们用一个附加程序定义了 记录器,它将日志放入控制台。

让我们再次运行 NoAppenderExample 类并检查控制台输出。结果,日志包含我们的语句:

2021-05-23 12:59:10 INFO Info log message

4.1.附加器可加性

不必为每个记录器定义附加程序。 给定记录器的日志记录请求将日志发送到为其定义的附加程序以及为层次结构中较高的记录器指定的所有附加程序。 让我们用一个例子来展示它。

如果记录器 A 定义了控制台附加程序,并且记录器 BA 的子级,则记录器 B 也会将其日志打印到控制台。 仅当中间祖先中的可加性标志设置为 true 时,记录器才会从其祖先继承附加程序。 如果可加性标志设置为 false ,则不会继承层次结构中较高级别的记录器的附加程序。

为了证明 记录器 从祖先继承了附加程序,让我们在 log4j.xml 文件中为 NoAppenderExample 添加一个 记录器

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
    ...
    <logger name="com.baeldung.log4j.NoAppenderExample" />
    ...
</log4j:configuration>

让我们再次运行 NoAppenderExample 类。这次,日志语句出现在控制台中。 尽管 NoAppenderExample 记录器没有显式定义的附加程序,但它从 记录器继承了附加程序

5.配置文件不在类路径上

现在让我们考虑一下我们想要在应用程序类路径之外定义配置文件的情况。我们有两个选择:

  • 使用 java 命令行选项指定文件的路径: -Dlog4j.configuration=
  • 在代码中定义路径: PropertyConfigurator.configure(“ ”);

在下一节中,我们将了解如何在 Java 代码中实现这一点。

6. 解决代码中的问题

假设我们不需要配置文件。让我们删除 log4.xml 文件并修改 main 方法:

public class NoAppenderExample {
    private final static Logger logger = Logger.getLogger(NoAppenderExample.class);

    public static void main(String[] args) {
        BasicConfigurator.configure();
        logger.info("Info log message");
    }
}

我们从 BasicConfigurator 类调用静态 配置 方法。它将 ConsoleAppender 添加到 记录器。我们看一下 configure 方法的源码:

public static void configure() {
    Logger root = Logger.getRootLogger();
    root.addAppender(new ConsoleAppender(new PatternLayout("%r [%t] %p %c %x - %m%n")));
}

由于 log4j 中的 记录器始终存在,因此我们可以通过编程方式向其添加控制台附加程序。

七、结论

关于如何解决有关缺少附加程序的 log4j 警告的简短教程到此结束。我们解释了什么是附加程序以及如何使用配置文件解决警告问题。然后,我们解释了附加器可加性的工作原理。最后,我们展示了如何解决代码中的警告。

与往常一样,该示例的源代码可以在 GitHub 上获取。