应用程序上下文被加载两次 - Spring Boot

时间:2014-06-27 06:09:36

标签: spring tomcat spring-boot

我有一个相当简单的设置。一个包含3个模块的maven项目:core / webapp / model。我正在使用Spring启动来设置我的应用程序。在webapp中,我有一个简单的WebappConfig类,如下所示:

@Configuration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = @ComponentScan.Filter(Configuration.class))
public class WebappConfig {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(WebappConfig.class);
        app.setAdditionalProfiles("dev");
        app.run(args);
    }
}

核心/模型模块中的几个类。我的容器应用点是:

public class AbcdXml extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(WebappConfig.class);
    }

}

没有web.xml!我的模型的pom具有以下与spring boot相关的依赖关系:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Core的pom.xml:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>

现在通过Run as - &gt;运行WebappConfig; Java应用程序运行完美,但我需要将项目部署为tomcat7上的战争。 Webapp的包装是战争。除了tomcat-jdbc和tomcat-tuli jar之外,lib中没有tomcat提供的jar(应该不是问题?)。

当我部署我的abcd.war时,applicationcontext被加载两次并导致跟随错误stracktrace:

2014-06-27 11:06:08.445  INFO 23467 --- [ost-startStop-1] o.a.c.c.C.[.[localhost].[/abcd]        : Initializing Spring embedded WebApplicationContext
2014-06-27 11:06:08.446  INFO 23467 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 19046 ms
2014-06-27 11:06:21.308  INFO 23467 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-06-27 11:06:21.313  INFO 23467 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'errorPageFilter' to: [/*]
2014-06-27 11:06:21.314  INFO 23467 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2014-06-27 11:06:26.073  INFO 23467 --- [ost-startStop-1] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2014-06-27 11:06:26.127  INFO 23467 --- [ost-startStop-1] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: default
    ...]
2014-06-27 11:06:26.511  INFO 23467 --- [ost-startStop-1] org.hibernate.Version                    : HHH000412: Hibernate Core {4.3.1.Final}
2014-06-27 11:06:26.521  INFO 23467 --- [ost-startStop-1] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2014-06-27 11:06:26.527  INFO 23467 --- [ost-startStop-1] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
//some info messages from spring boot
2014-06-27 11:07:31.664  INFO 23467 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-06-27 11:07:33.095  INFO 23467 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-06-27 11:07:33.096  INFO 23467 --- [ost-startStop-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2014-06-27 11:07:36.080  INFO 23467 --- [ost-startStop-1] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-06-27 11:08:49.583  INFO 23467 --- [ost-startStop-1] o.s.boot.SpringApplication               : Started application in 183.152 seconds (JVM running for 210.258)
2014-06-27 11:12:29.229 ERROR 23467 --- [ost-startStop-1] o.a.c.c.C.[.[localhost].[/abcd]        : Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener

java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:277)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:976)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1653)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

我之前没有提到过web.xml。

很少有趣的事情我无法弄清楚原因:

  1. 在爆炸战争之后,tomcat以某种方式创建了一个带有默认web.xml的ROOT文件夹[必须是Spring引导配置错误。我怎么能纠正它?指针好吗?]
  2. 即使我在AbcdXml.java中返回相同的“应用程序”SpringApplicationBuilder,我也面临同样的问题,即applicationcontext被加载了两次。
  3. 感谢您的帮助!

    编辑1:

    在ROOT文件夹中生成的web.xml的内容:

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" version="2.5">
    </web-app>
    

6 个答案:

答案 0 :(得分:13)

如果您的应用包含jersey-spring3并且您没有采取措施禁用,它会尝试为您创建ApplicationContext(有帮助,而不是)。有一种方法可以将其关闭(在WebApplicationInitializer中):

servletContext.setInitParameter("contextConfigLocation", "<NONE>");

或者只使用它:https://github.com/dsyer/spring-boot-jersey(包括作为依赖项)。

答案 1 :(得分:2)

在我的情况下 - 我遇到了同样的问题 - 看到Spring splash screen两次 - 这是因为我有2个类扩展SpringBootServletInitializer。一个称为SpringBootWebApplication,另一个称为ServletInitializer。我刚删除了ServletInitializer,它运行正常。不知道为什么有两个班级 - 也许是因为我从两个不同的例子中得到启发来组装我需要的东西。

答案 2 :(得分:1)

在我的情况下,罪魁祸首是使用Spring Boot 1.3.0.M4,以及Jersey 2.21。当我将Spring Boot降级到1.2.6.RELEASE时,问题就消失了。 我唯一要做的就是显式覆盖以下属性,因为我需要Spring 4.2.0 for Hibernate 5支持,而jackson 2.6.2 for JSR310(java8 java.time)支持:

<spring.version>4.2.0.RELEASE</spring.version>
<jackson.version>2.6.2</jackson.version>

编辑:从spring-boot 1.3.0.RELEASE开始,这个bug仍然存在。见github

答案 3 :(得分:0)

我的主要问题是我的spring上下文被加载了两次。当我打印每个类的类加载器时,我发现我的应用程序正在运行两次。 (即,当我按F9后在intellij中进行调试时,我又重新回到了同一行,即

ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigAssignServer.class, args);

我的问题出在pom.xml中。我从pom中删除了以下依赖项,并且有效。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
</dependency>

请检查您的依赖性。希望它能帮助某人。享受编码:)

答案 4 :(得分:0)

我遇到了同样的问题

我有src> main> webapp> WEB-INF> web.xml有一个要说的实体

<listener>
	<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>

这是第二次加载我的上下文。

注释掉它,它将只加载一次。

答案 5 :(得分:-1)

来自API的

@EnableAutoConfiuguration说“启用Spring Application Context的自动配置,尝试猜测和配置您可能需要的bean。”

@ComponentScan也会实例化bean。 IT将扫描包,查找并注册bean。

当你使用这两个注释时,我想这就是它加载两次的原因。