【问题标题】:log4j2 configuration file not found with java 9java 9找不到log4j2配置文件
【发布时间】:2017-09-10 08:49:38
【问题描述】:

我有一个 Java 8 项目,我的配置文件位于资源文件夹中,一切正常。现在我切换到Java 9,添加了log4j.api 的要求,并且找不到配置文件了。

我是否需要在我的 module-info 文件中添加其他内容以便记录器找到它的配置?

现在是这样的

module project.main {
    requires jdk.incubator.httpclient;
    requires jackson.databind;
    requires jackson.core;
    requires jackson.annotations;
    requires log4j.api;
}

项目结构如下:

build.gradle 文件如下:

【问题讨论】:

  • 您当前的目录结构是什么?您在 java 8 中映射资源的方式是什么?
  • @nullpointer - src/main/java - src/main/resources - src/main/java/package1 - src/main/java/package2 - src/main/java/module-info.java - src/main/resources/log4j2.xml 但是我不确定第二个问题,我自己并没有真正做任何映射,只是添加了依赖并创建了配置文件,就是这样。
  • 您能否在问题本身中更新项目结构的屏幕截图/层次结构?另外,你是如何导入 log4j 模块的?请提及使用的 jar/artifact 的版本。
  • 如果 log4j2.xml (sp?) 在 JDK 8 中找到,那么它也应该在 JDK 9 中找到。模块顶层目录中的资源不被封装。如果配置文件位于不同的位置,比如 foo/resources/log4j.xml,那么它将被封装,并且模块需要 opens foo.resources 以允许扫描类路径的库(如 log4j)找到它。跨度>
  • @nullpointer 我认为该评论会保存我的格式,添加图像。使用 gradle 导入 log4j,版本为 2.9.0

标签: java log4j2 java-9 module-info


【解决方案1】:

log4j~faq 建议至少使用log4j-api-2.xlog4j-core-2.x。最好将这些添加到您的 build.gradle 文件中:

compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.9.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.9.0'

并确保conflicting dependencies are excluded


module-info.java 进一步更新(这是我在custom maven project 中所做的)

requires log4j; // not log4j.api

它应该也适用于您,并且具有相同的目录结构。


提示:这是我开始调试它的地方。 Why do I see a warning about "No appenders found for logger" and "Please configure log4j properly"?

当默认配置文件 log4j.properties 和 找不到 log4j.xml 并且应用程序没有执行显式 配置。 log4j 使用Thread.getContextClassLoader().getResource() 定位到默认配置文件,不直接检查 文件系统...

ClassLoader#getResource 方法中放置了一个调试点,并密切关注库查找的资源。


还提出了resources/foo/bar/log4j.properties 等资源的观点,如JDK-8142968 中的发行说明中所述

  • JDK 内部资源,除了类​​文件,在标准和 JDK 模块中不能再用 ClassLoader.getResourceXXXAPI。这可能会影响依赖于 使用这些 API 获取 JDK 内部属性文件或其他 资源。

并得到ClassLoader#getResource 的 java-doc 的支持:

  • 命名模块中的资源受封装规则的约束 由Module.getResourceAsStream 指定。此外,除了 资源名称以“.class”结尾的特殊情况, 此方法只会在命名模块的包中查找资源 包是无条件打开的(即使这个的调用者 方法与资源在同一个模块中)。

【讨论】:

  • 如果 log4j-api-2.9.0.jar 用作自动模块,则派生名称为“log4j.api”,因此问题中的requires 指令看起来正确。由于 log4j 是可插拔的,因此它需要一个实现,在这种情况下可能是 log4j-core-2.9.0.jar 中的实现。您应该能够在模块路径或类路径上部署实现,API 会找到它。至于配置文件 log4j2.xml 那么将位于模块 project.main 的顶级目录中。如果它在类路径上,也会被找到。
  • @Alan 我使用的指令是由 intelliJ 建议的,但我也怀疑自动模块是否会这样命名。尝试 log4j.api 也不能作为模块解析。猜猜我必须为这种情况手动创建模块?与资源相关,我的理解是,访问它们的方式在内部资源的封装方面发生了变化,而不是顶级目录..如果我错了,请纠正我。
  • 非常感谢您的回答。我创建了 maven 项目并且一切正常,但是当我尝试使用 Java 9 创建 gradle 项目以查看它是否有效时,我实际上得到了一个错误“错误:BUG!源单元中的“类生成”阶段异常'BuildScript ' unsupported Target MODULE" ,google了一下,发现最近有人遇到了同样的问题。所以实际上可能与 gradle 有关。无论如何,谢谢你这么长时间坚持这个问题!
  • @EmberTraveller 您可以将其作为 gradle 跟踪器中的错误提出。希望有人会回来修复它。
  • @nullpointer - log4j 附带一个名为 log4j-1.2-api-2.9.0.jar 的 JAR 文件,用于使用旧 log4j API 的应用程序进行桥接。如果用作自动模块,它的模块名称将为“log4j”。关于 log4j2.xml 是否是封装的问题,答案是“否”,因为它是顶级目录。顶级目录相当于未命名的包,因此不是模块的成员(因为模块只包含命名的包)。
猜你喜欢
  • 2014-10-18
  • 2014-12-30
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 2018-01-02
  • 1970-01-01
  • 2018-08-27
  • 2016-10-24
相关资源
最近更新 更多