【问题标题】:Log4j2 web look up cannot access servletcontext attributeLog4j2 web 查找无法访问 servletcontext 属性
【发布时间】:2015-02-12 18:22:10
【问题描述】:

我们使用的是 Tomcat 7.0.54。

web.xml:

<context-param>
    <param-name>log4jContextName</param-name>
    <param-value>SabaLog4jContext</param-value>
</context-param>

有一个在加载时启动的示例 servlet

    <servlet>
        <servlet-name>startUp</servlet-name>
        <servlet-class>foo.StartupServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

StartupServlet 简单如下:

public class StartupServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        getServletContext().setAttribute("test", "ATest");
        super.init();
    }

}

log4j2 无法使用${web:attr.test} 访问test 属性,我收到以下警告:

INFO: org.apache.logging.log4j.web.WebLookup unable to resolve key 'test'

Log4j2 似乎工作正常,但问题是它在我的启动之前启动。我尝试使用 servletContextListener 类但没有运气。

我还尝试在 web.xml 中禁用 Log4jAutoInitialization 并手动开始设置它们,如下所示。

 <listener>
    <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>

<filter>
   <filter-name>log4jServletFilter</filter-name>
   <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>log4jServletFilter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>INCLUDE</dispatcher>
  <dispatcher>ERROR</dispatcher>
</filter-mapping>

但没有运气:(

log4j2.xml如下:

<property name="baseFolder">${web:rootDir}/../logs/${web:test}</property>

那么如何设置我的 web.xml 以便我的代码在 Log4j 上下文之前执行。

web.xml 还包含 spring 监听器:

  <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

【问题讨论】:

  • 你能发布你的 log4j2.xml 吗?你在哪里使用${web:attr.test}?另外,不要忘记在 log4j-user 邮件列表 (logging.apache.org/log4j/2.x/mail-lists.html) 上提出这个问题或提出 Jira 票。
  • 我已经更新了这个问题。正如我所提到的,问题似乎是加载顺序,log4j 总是在其他 servlet 到 ServletContextListner 之前启动。我还通过电子邮件发送到邮件列表。

标签: servlets servlet-filters log4j2 servlet-3.0 servletcontextlistener


【解决方案1】:

首先,确保将 Tomcat 配置为在您的 web.xml 文件中提供 servlet 3.0 容器的功能:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

您将需要 3.0 功能,以便您可以指定加载 servlet 的顺序。然后,您需要拥有自己的 ServletContainerInitializer 来初始化 ServletContext 属性。这是我的一个sn-p:

/* Initializer that is configured, via web.xml, to initialize before Log4j2's initializer.  This gives us the
 * opportunity to set some servlet context attributes that Log4j2 will use when it eventually initializes.
 */

public class BitColdHardCashContainerInitializer implements ServletContainerInitializer {

    @Override
    public void onStartup(final Set<Class<?>> classes, final ServletContext servletContext) throws ServletException {
        if (servletContext.getMajorVersion() > 2) {
            servletContext.log("BitColdHardCashContainerInitializer starting up in Servlet 3.0+ environment.");

        }

        // Set the webapp.name attribute so that Log4j2 may use it to create a path for log files.
        servletContext.setAttribute("webapp.name", servletContext.getContextPath().replaceAll("/", "").trim());

接下来,您希望 ServerContainerInitializer 在 Log4j2 之前运行。在您的 web.xml 中,为您的 servlet 命名:

<absolute-ordering>
    <name>BitColdHardCash</name>
    <others/>
</absolute-ordering>

这需要在&lt;servlet&gt; 元素之前指定。

创建一个web-fragment.xml 文件:

<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                                  http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
              version="3.0" metadata-complete="true">
    <name>BitColdHardCash</name>
    <distributable />
    <ordering>
        <before>
            <others />
        </before>
    </ordering>
</web-fragment>

这告诉 Tomcat 首先初始化您的 ServletContainerInitializer,然后再进行其他任何操作,包括 Log4j2 的。这在 META-INF 目录中。

应该这样做。要检查的另一件事是您的catalina.properties 文件。您使用的 Tomcat 版本修复了有关调用 ServletContextInitializers 的错误。我不确定该错误是在 Tomcat 源代码中还是在默认提供的 catalina.properties 文件中。如果您使用的是在修复之前的 catalina.properties 文件,只需将其打开并确保 log4j*.jar 不包含在为 tomcat.util.scan.DefaultJarScanner.jarsToSkip 属性指定的文件列表中。

【讨论】:

  • 订购是我想要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 2015-05-03
  • 2018-04-24
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多