Spring 没有 web.xml log4j 配置的应用程序

Spring application without web.xml log4j configuration

我有一个 Spring + Jersey Web 应用程序,我正在从 web.xml 迁移到注释基础配置。我正在实施 WebApplicationInitializer,除 log4j 外一切正常,因为我有一个自定义文件名。

在 web.xml 我有

<context-param>
    <param-name>log4jConfiguration</param-name>
    <param-value>/WEB-INF/custom-name-log4j.xml</param-value>
</context-param>

这有效。

现在,我尝试在 Java 中做同样的事情:

container.setInitParameter("log4jConfiguration", "/WEB-INF/custom-name-log4j.xml");

这不起作用...我在 Tomcat 7.0.62 中收到以下错误:

ERROR StatusLogger No Log4j context configuration provided. This is very unusual.
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

我的 WAR 文件包含 WEB-INF/ 文件夹中的 xml。

除了指定 log4jConfiguration 参数,我还需要做更多的事情吗?

稍后编辑: WebApplicationInitializer

    @Override
    public void onStartup(ServletContext container) {
        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();
        rootContext.register(MyApplicationConfiguration.class);

        container.setInitParameter("log4jConfiguration", "/WEB-INF/custom-name-log4j.xml");

        rootContext.setConfigLocation("my.package.spring");

        final FilterRegistration.Dynamic characterEncodingFilter = container.addFilter("characterEncodingFilter", new CharacterEncodingFilter());
        characterEncodingFilter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
        characterEncodingFilter.setInitParameter("encoding", "UTF-8");
        characterEncodingFilter.setInitParameter("forceEncoding", "true");

        container.setInitParameter("spring.profiles.default", "prod");

        rootContext.register(SecurityContextFilter.class);

        container.addListener(new ContextLoaderListener(rootContext));
        container.addListener(new RequestContextListener());

        container.setInitParameter("contextConfigLocation", "");

        final ServletContainer servlet = new ServletContainer();
        final ServletRegistration.Dynamic appServlet = container.addServlet("appServlet", servlet);
        appServlet.setInitParameter("jersey.config.server.provider.packages", "my.package");
        appServlet.setLoadOnStartup(1);

        final Set<String> mappingConflicts = appServlet.addMapping("/rest/*");

    }

您还需要注册一个监听器:Log4jConfigListener(您可以在org.springframework.web.util中找到它)

servletContext.addListener(Log4jConfigListener.class);

顺便说一句,你可以注意到它是deprecated since spring 4.2.1

编辑

抱歉,我没有意识到您正在使用 log4j2, 上面所说的一切都是错误的,这里是你的解决方案:

log4j2(感谢 log4j-web 工件)和 spring 都依赖于 servlet 3.0 API 中的 ServletContainerInitializer 来设置 ServletContext . 问题是它们的执行顺序取决于它们在类路径上扫描的顺序,你不能真正依赖它(在你的情况下, Log4jServletContainerInitializer 启动方法在 SpringServletContainerInitializer).

要更正此问题,您可以声明自己的 ServletContainerInitializer 实现,我们将在其他人之前(在扫描类路径之前)考虑它,这里是一个示例:

public class Log4j2ConfigServletContainerInitializer implements ServletContainerInitializer {

    @Override
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        ctx.setInitParameter("log4jConfiguration", "/WEB-INF/custom-name-log4j.xml");
    }
}

然后你必须创建一个文件: /META-INF/services/javax.servlet.ServletContainerInitializer

并放入其中:

example.initializer.Log4j2ConfigServletContainerInitializer (根据您的需要进行更改)

您提供的用于设置自定义 log4j 配置文件位置的配置将在触发 Log4jServletContainerInitializer 之前设置,一切都会好起来的。

见:

https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContainerInitializer.html

http://www.eclipse.org/jetty/documentation/current/using-annotations.html#servlet-container-initializers

http://logging.apache.org/log4j/2.x/manual/webapp.html

编辑

POC @ http://www.filedropper.com/32713596_1 只是 运行 mvn jetty:run