Log4j2 web查找无法访问servletcontext属性

时间:2014-12-14 15:25:05

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

我们正在使用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无法使用test访问${web:attr.test}属性,我收到警告:

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

似乎Log4j2工作正常,但问题是它在我的Startup之前启动。我尝试使用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 Listeners:

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

1 个答案:

答案 0 :(得分: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属性。这是我的一个片段:

/* 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>

这需要在<servlet>元素之前指定。

创建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&#39; s。这位于META-INF目录中。

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