以编程方式加载 Log4j2 配置文件
Posted
技术标签:
【中文标题】以编程方式加载 Log4j2 配置文件【英文标题】:Load Log4j2 configuration file programmatically 【发布时间】:2014-01-31 18:12:41 【问题描述】:我想从我的应用程序中以编程方式加载 Log4j2 XML 配置文件。
试过这个:
ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
Configurator.initialize(null, source);
还有这个:
ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
ConfigurationFactory factory = (ConfigurationFactory) XMLConfigurationFactory.getInstance().getConfiguration(source);
ConfigurationFactory.setConfigurationFactory(factory);
但还没有任何效果。
【问题讨论】:
在 log4j2 中重新加载配置时引入了所有向后不兼容的更改,因此指定您正在使用的 log4j2 api 和核心版本是有意义的... 【参考方案1】:对于最新版本的 log4j,以下是加载外部 log4j2.xml
的方法:
String log4jConfigFile = System.getProperty("user.dir") + File.separator + "log4j2.xml";
ConfigurationSource source = new ConfigurationSource(new FileInputStream(log4jConfigFile));
Configurator.initialize(null, source);
【讨论】:
你应该可以简单地使用Configurator.initialize(null, "fileName");
为什么将 null 传递给 Configurator.initialize() ?【参考方案2】:
如果您只有一个主入口点,此代码 sn-p 可能会为您节省一些麻烦。 set 属性调用必须在创建任何记录器之前触发。这种方法适用于类路径中的文件。
public class TestProcess
static
System.setProperty("log4j.configurationFile", "log4j-alternate.xml");
private static final Logger log = LoggerFactory.getLogger(TestProcess.class);
【讨论】:
这很好用,我试图在构造函数上设置属性,但是没有用。静态块已解决。 我有 setProperty() 调用,但不在“静态”块中。一旦我将调用保留在静态块中,它就起作用了。谢谢! 更改系统属性不会影响其他记录器的吗?【参考方案3】:自己找到了答案。有人可能会觉得它很有用。
ConfigurationSource source = new ConfigurationSource();
source.setLocation(logConfigurationFile);
source.setFile(new File(logConfigurationFile));
source.setInputStream(new FileInputStream(logConfigurationFile));
Configurator.initialize(null, source);
【讨论】:
我正在尝试做同样的事情,但即使使用上面的代码也失败了。您的项目中是否有 log4j2 Web 依赖项?我的 log4j2.xml 在类路径之外,我正在尝试将其加载到具有 @PostConstruct 方法的 Spring bean 中。 我的日志 xml 配置文件在类路径之外。 您的应用程序是 Web 应用程序吗?我应该提到我也在使用 slf4j 来抽象 log4j2。 是的,它是一个网络应用程序。我还使用slf4j
将jcl
日志路由到log4j2
。
好吧,酷。这个答案是基于 Servlet 2.5 ......无论如何它的工作都很棒!【参考方案4】:
下面为我工作,Log4j2 和 SLF4J 包装器:
解决方案 1:
public class MyClass
static
try
InputStream inputStream = new FileInputStream("C:/path/to/log4j2.xml");
ConfigurationSource source = new ConfigurationSource(inputStream);
Configurator.initialize(null, source);
catch (Exception ex)
// Handle here
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class); // LogManager if not using SLF4J
public void doSomething()
LOGGER.info(...)
解决方案 2:
static
File log4j2File = new File("C:/path/to/log4j2.xml");
System.setProperty("log4j2.configurationFile", log4j2File.toURI().toString());
需要toURI()
关注File URI Scheme format,否则会抛出MalformedURLException
。
来源:
Proper format for log4j2.xml RollingFile configuration https://github.com/jprante/elasticsearch-jdbc/issues/562 https://www.codeproject.com/Questions/190269/MalformedURLException-unknown-protocol-c-How-to-ha https://coderanch.com/t/633544/open-source/java-net-MalformedURLException-initialize-log【讨论】:
如果我的是 .properties 文件怎么办 @silver 为什么将 null 传递给 Configurator.initialize() ?【参考方案5】:如果您使用的是 Servlet 3.0 Web 应用程序,您可以使用 Log4jServletContextListener 并执行以下操作:
编写一个从Log4jServletContextListener
扩展的自定义LogContextListener
,在您的web.xml
中设置它并禁用自动初始化:
<listener>
<listener-class>com.example.LogContextListener</listener-class>
</listener>
<context-param>
<param-name>isLog4jAutoInitializationDisabled</param-name>
<param-value>true</param-value>
</context-param>
在您的自定义LogContextListener
中覆盖contextInitialized
并设置配置位置
public void contextInitialized(ServletContextEvent event)
/* Some logic to calculate where the config file is saved. For
* example you can read an environment variable.
*/
String pathToConfigFile = ... + "/log4j2.xml";
Configurator.initialize(null, pathToConfigFile);
super.contextInitialized(event);
比直接在web.xml
中配置位置的优势在于
您可以根据一些附加信息计算路径并访问 log4j2.xml,即使它在您的类路径之外。
【讨论】:
我在 log4j 1.2.x 中使用了类似的解决方案,但无法使用 2.14.x。原因是,我的“LogContextListener”是在 log4j2 已经用WARN StatusLogger No Log4j 2 configuration file found. Using default configuration...
初始化之后创建的@ 我的监听器是 web.xml 中的第一个监听器,但之前触发的 TLD 文件中还有其他监听器。【参考方案6】:
考虑 - https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/config/Configurator.html
Configurator.initialize(null, "classpath:conf/logger.xml");
or
Configurator.initialize(null, "/full_path/conf/logger.xml");
注意,不要同时使用两者。
【讨论】:
为什么将 null 传递给 Configurator.initialize() ? 请检查上面的javadoc链接。 第一个参数是类加载器,但 javadoc 并没有提供更多信息;如果我正确理解了代码,如果 null 它将使用用于加载 log4j2 的类加载器(更准确地说是 Configurator.class.getClassloader())【参考方案7】:final URL log4j = Resources.getResource("log4j2-test.xml");
LoggerContext.getContext(false)
.start(new XmlConfiguration(new ConfigurationSource(
Resources.asByteSource(log4j).openStream(),
log4j)));
【讨论】:
仅供参考 - 小心使用“log4j2-test.xml”进行测试。如果这是在 log4j2 检查的任何文件夹中,它将在“log4j2.xml”上使用它,并让您认为您对此的覆盖有效,而实际上并没有。我没有尝试过你的代码,但是我之前的代码 sn-p 遇到了这个问题。我在使用“log4j2-test.xml”时认为一切都在运行时被覆盖,结果发现它被覆盖了,因为 log4j2 首先查找“log4j2-test.xml”,然后是“log4j2.xml”logging.apache.org/log4j/2.0/manual/… @TJR 它是否也适用于新的 CompositeConfiguration() 而不是新的 XmlConfiguration()?【参考方案8】:如果您使用 .properties 文件进行配置:
String propertiesFile = "./test/Configuration/log4j2.properties";
ConfigurationSource source = new ConfigurationSource(new FileInputStream(propertiesFile), new File(propertiesFile));
Configurator.initialize(null, source);
【讨论】:
以上是关于以编程方式加载 Log4j2 配置文件的主要内容,如果未能解决你的问题,请参考以下文章