如何将TomcatEmbeddedServletContainerFactory与AbstractAnnotationConfigDispatcherServletInitializer一起使用

如何将TomcatEmbeddedServletContainerFactory与AbstractAnnotationConfigDispatcherServletInitializer一起使用,tomcat,spring-boot,Tomcat,Spring Boot,我从Spring Boot项目中找到了“TomcatEmbeddedServletContainerFactory”,它可以创建一个Tomcat嵌入式实例。 我已经有了一组“传统的”Spring(基于Java)配置类,外加一个“AbstractAnnotationConfigDispatcherServletInitializer”实现,用于设置根应用程序上下文和控制器上下文 public class IntegrationTestDispatcherServletInitializer ext

我从Spring Boot项目中找到了“TomcatEmbeddedServletContainerFactory”,它可以创建一个Tomcat嵌入式实例。 我已经有了一组“传统的”Spring(基于Java)配置类,外加一个“AbstractAnnotationConfigDispatcherServletInitializer”实现,用于设置根应用程序上下文和控制器上下文

public class IntegrationTestDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected String[] getServletMappings() {
    return new String[]{"/"};
}

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[]{ServiceModuleConfiguration.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[]{WebModuleConfiguration.class };
}
}
getEmbeddedServletContainer()需要一个来自Spring boot的ServletContextInitializer,现在我不得不将它连接到我的配置类


Spring Boot的tomcat工厂是为支持这一点而建立的吗?如果是,有什么例子吗?

嵌入式ServletContainerFactory确实与
嵌入式WebApplicationContext配对(不是从
AbstractAnnotationConfigDispatchersServletInitializer
获得的
注释ConfigWebApplicationContext
)。如果要构建WAR文件,那么鉴于初始值设定项的简单性质,最好的选择是使用
SpringApplicationServletInitializer
,例如

public class IntegrationTestDispatcherServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(ServiceModuleConfiguration.class).child(WebModuleConfiguration.class);
    }

}

如果您不想要WAR文件(如评论中所建议的,当我仔细考虑它时),只需创建一个
SpringApplication
,如果它认为您正在尝试构建一个webapp(或使用上面代码中的生成器),它将使用
EmbeddedServletContainerFactory
.

通过更多的调试和Dave的更多输入,正确的方法是显式获取子生成器实例并调用其run()方法。这将正确启动上下文

    SpringApplicationBuilder builder = new SpringApplicationBuilder();
    builder.sources(ServiceModuleConfiguration.class);
    childBuilder = builder.child(WebModuleConfiguration.class, WebConfiguration.class, TomcatContainerFactoryConfigur‌​ation.class);
    childBuilder.run();
WebConfiguration
包含
DispatcherServlet
bean

    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        return new ServletRegistrationBean(new DispatcherServlet((WebApplicationContext) applicationContext), "/*");
    }
TomcatContainerFactoryConfigur‌​ation
包含
TomcatEmbeddedServletContainerFactory
bean

    @Bean
    public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
        return new TomcatEmbeddedServletContainerFactory("", 8080);
    }

我没有让
SpringServletContainerInitializer
启动web应用程序。我使用的是
AnnotationConfigEmbeddedWebApplicationContext
EmbeddedServletContainerFactory
的bean定义。容器本身启动,但我猜是为了实现上述
IntegrationTestDispatchrServletInitializer
必须运行
SpringServletContainerInitializer
吗?是的,对不起,我不知道您想做什么。如果您不想构建war文件并部署它,那么
ServletContextInitializer
将不会有帮助,如果您想要嵌入式容器,您可能不想要war文件。为什么不呢st使用
SpringApplication
或直接使用构建器?好的,我们将对此进行调查。我的目的是从嵌入式tomcat运行一个简单的集成测试,而不用构建WAR并部署它。
SpringApplicationBuilder=new SpringApplicationBuilder(WebModuleConfiguration.class,ServiceModuleConfiguration.class);builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);builder.application().run()
这是启动上下文,但是它看起来并没有给我一个正常的DispatcherServlet设置。但是现在的问题是,如果我必须像使用
AbstractDispatcherServletInitializer那样手动注册它,我将需要使用控制器bean访问应用程序上下文?我看不出如何使用它从构建器/应用程序中获取et?是的,我明白了。要获得一个
DispatcherServlet
来拥有您的上下文,您需要创建一个该类型的
@Bean
,并将其放在您的应用程序上下文中。这应该不是什么大问题吗?注意,要从原始应用程序中保留应用程序上下文层次结构,您需要使用
SpringApplic就像上面的示例中一样,是AnationBuilder
(或同等产品)。也许您的原始应用不需要这种层次结构(大多数应用不需要)。
    @Bean
    public EmbeddedServletContainerFactory embeddedServletContainerFactory() {
        return new TomcatEmbeddedServletContainerFactory("", 8080);
    }