没有web.xml log4j配置的Spring应用程序 [英] Spring application without web.xml log4j configuration

查看:597
本文介绍了没有web.xml log4j配置的Spring应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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);

顺便说一句,您可以注意到它是

然后,您必须创建一个文件: /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

I have a Spring + Jersey web application that I'm migrating from a web.xml to annotation base configuration. I'm implementing WebApplicationInitializer and everything works except log4j, because I have a custom file name.

In the web.xml I had

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

This worked.

Now, I tried to do the same in Java:

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

This doesn't work... I get the following errors in 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.

My WAR file contains the xml in the WEB-INF/ folder.

Do I have to do more than specifying that log4jConfiguration parameter?

Later Edit: 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/*");

    }

解决方案

You also need to register a Listener : Log4jConfigListener (you can find it in org.springframework.web.util)

servletContext.addListener(Log4jConfigListener.class);

By the way, you can note that it is deprecated since spring 4.2.1

EDIT

Sorry I didn't realized that you were using log4j2, everything stated above is false, and here is the solution for you :

log4j2 (thanks to log4j-web artifact) & spring are both relying on ServletContainerInitializer from servlet 3.0 API to setup the ServletContext. The problem is that the order they are executed depends on the order they are scanned on the classpath and you can't really rely on it (in your case the Log4jServletContainerInitializer startup methods is called before the one from SpringServletContainerInitializer).

To correct this you can declare your own ServletContainerInitializer implementation which we'll be taken into account before others (before scanning the classpath) and here is a sample :

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");
    }
}

Then you have to create a file : /META-INF/services/javax.servlet.ServletContainerInitializer

and put into it :

example.initializer.Log4j2ConfigServletContainerInitializer (change to suit your needs)

and the configuration you provided to set a custom log4j config file location will be set before triggering the Log4jServletContainerInitializer and everything is going to be fine.

see :

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

EDIT

POC @ http://www.filedropper.com/32713596_1 just run mvn jetty:run

这篇关于没有web.xml log4j配置的Spring应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆