Java 如何从JNDI加载log4j2配置文件

Java 如何从JNDI加载log4j2配置文件,java,jakarta-ee,logging,log4j,log4j2,Java,Jakarta Ee,Logging,Log4j,Log4j2,我正在将一些web应用程序从log4j1.12迁移到Log4j2。由于公司的政策,我们的log4j.xml文件位置在应用服务器中配置为URL,应用程序必须使用JNDI获取它们。我们实现了一个ServletContextListener,它允许我们以这种方式初始化log4j基础结构: public void contextInitialized(ServletContextEvent servletContextEvent) { ... urlLogConfig = (URL) c

我正在将一些web应用程序从log4j1.12迁移到Log4j2。由于公司的政策,我们的log4j.xml文件位置在应用服务器中配置为URL,应用程序必须使用JNDI获取它们。我们实现了一个
ServletContextListener
,它允许我们以这种方式初始化log4j基础结构:

public void contextInitialized(ServletContextEvent servletContextEvent) {
    ...
    urlLogConfig = (URL) context.lookup("java:comp/env/"+logLocation);
    ...
    //urlLogConfig -> file:///somepath/log4j.xml
    DOMConfigurator.configureAndWatch(urlLogConfig.getPath());
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ServletContext servletContext = servletContextEvent.getServletContext();
    servletContext.log("Log4jConfigurationListener - Shutting down log4j");
    LogManager.shutdown();
}
但是,随着log4j2api的更改,这将无法再使用。Log4j2提供了lo4j2-web.jar模块,该模块使用
log4jservletcontainerinInitializer
初始化库。这将调用
Log4jWebInitializerImpl.getConfigURI()
,负责获取配置文件的URI


有没有办法自定义Log4jWebInitializerImpl的行为,使其从JNDI名称解析xml文件?

类似于:

...
import org.apache.logging.log4j.core.config.Configurator;
...

    private LoggerContext loggerContext;

    public void contextInitialized(ServletContextEvent servletContextEvent) {
       ...
       urlLogConfig = (URL) context.lookup("java:comp/env/"+logLocation);
       ...
       //urlLogConfig -> file:///somepath/log4j.xml
       ServletContext servletContext = servletContextEvent.getServletContext();
       String contextName = servletContext.getServletContextName();
       Classloader classloader = this.getClass().getClassloader();
       loggerContext = Configurator.initialize(contextName, classloader, urlLogConfig.toURI());
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();
        servletContext.log("Log4jConfigurationListener - Shutting down log4j");
        if (loggerContext != null) 
             Configurator.shutdown(loggerContext);
    }

嗨,史蒂夫,你的解决方案还可以。然而,我有点担心这里所说的
Log4j资源无法通过正常方式清理。当web应用程序部署时,Log4j必须“启动”,当web应用程序取消部署时,Log4j必须“关闭”
您是否确定您提出的方案将正确清理web环境中的所有内容?上述解决方案不使用log4j2 webapp包`Configurator.shutdown(loggerContext)应该清理它自己初始化的资源。