SpringBoot使用外部Web容器的解决方案

打印 上一主题 下一主题

主题 896|帖子 896|积分 2688

Spring Boot 默认内嵌了Web容器(如Tomcat、Jetty或Undertow),这使得应用可以作为独立的可执行JAR或WAR文件运行,无需外部Web容器。然而,在某些情况下,你可能想要将Spring Boot应用部署到外部的Web容器中,比如Apache Tomcat或Jetty。
嵌入式的Web容器:应用可以打包成可执行的Jar。
优点:简单、便携。
缺点:默认不支持JSP、优化定制比较复杂(使用定制器ServerProperties、自定义EmbeddedServletContainerCustomizer,自己编写嵌入式Servlet容器的创建工厂EmbeddedServletContainerFactory)。
外部的Web容器:表面安装Tomcat服务器,应用war包的方式打包运行。
解决步调

将Spring Boot应用部署到外部的Web容器的步调:
1.创建一个Maven项目,声明为WAR。
2.排除内嵌Tomcat容器
  1. <dependency>  
  2.     <groupId>org.springframework.boot</groupId>  
  3.     <artifactId>spring-boot-starter-web</artifactId>  
  4.     <exclusions>  
  5.         <exclusion>  
  6.             <groupId>org.springframework.boot</groupId>  
  7.             <artifactId>spring-boot-starter-tomcat</artifactId>  
  8.         </exclusion>  
  9.     </exclusions>  
  10. </dependency>
复制代码
3.重新导入Tomcat启动器,依赖范围改为provided
  1. <dependency>
  2.    <groupId>org.springframework.boot</groupId>
  3.    <artifactId>spring-boot-starter-tomcat</artifactId>
  4.    <scope>provided</scope>
  5. </dependency>
复制代码
4.必须编写一个SpringBootServletInitializer的子类,并调用configure方法
  1. public class ServletInitializer extends SpringBootServletInitializer {
  2.    @Override
  3.    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  4.        //传入SpringBoot应用的主程序
  5.       return application.sources(SpringBootWebApplication.class);
  6.    }
  7. }
复制代码
5.启动服务器就可以使用。
底层原理

JAR包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器。
WAR包:启动Tomcat服务器,服务器启动SpringBoot应用SpringBootServletInitializer,然后启动ioc容器。
查看Servlet3.0及以上的运行规则
1)服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer实例。
2)ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为javax.servlet.ServletContainerInitializer的文件,内容就是ServletContainerInitializer的实现类的全类名。
3)还可以使用@HandlesTypes,在应用启动的时间加载我们感兴趣的类。
流程
1.启动Tomcat
2.查看文件内容
org\springframework\spring-web\4.3.14.RELEASE\spring-web-4.3.14.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer:
Spring的web模块里面有这个文件:org.springframework.web.SpringServletContainerInitializer
3.SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有这个类型的类都传入到onStartup方法的泛型参数Set中;为这些WebApplicationInitializer类型的类创建实例
4.每一个WebApplicationInitializer都调用自己的onStartup

5.相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法
6.SpringBootServletInitializer实例执行onStartup的时间会createRootApplicationContext,创建容器。源码查看:
  1. protected WebApplicationContext createRootApplicationContext(
  2.       ServletContext servletContext) {
  3.     //1、创建SpringApplicationBuilder
  4.    SpringApplicationBuilder builder = createSpringApplicationBuilder();
  5.    StandardServletEnvironment environment = new StandardServletEnvironment();
  6.    environment.initPropertySources(servletContext, null);
  7.    builder.environment(environment);
  8.    builder.main(getClass());
  9.    ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
  10.    if (parent != null) {
  11.       this.logger.info("Root context already created (using as parent).");
  12.       servletContext.setAttribute(
  13.             WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
  14.       builder.initializers(new ParentContextApplicationContextInitializer(parent));
  15.    }
  16.    builder.initializers(
  17.          new ServletContextApplicationContextInitializer(servletContext));
  18.    builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
  19.    
  20.     //调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来
  21.    builder = configure(builder);
  22.    
  23.     //使用builder创建一个Spring应用
  24.    SpringApplication application = builder.build();
  25.    if (application.getSources().isEmpty() && AnnotationUtils
  26.          .findAnnotation(getClass(), Configuration.class) != null) {
  27.       application.getSources().add(getClass());
  28.    }
  29.    Assert.state(!application.getSources().isEmpty(),
  30.          "No SpringApplication sources have been defined. Either override the "
  31.                + "configure method or add an @Configuration annotation");
  32.    // Ensure error pages are registered
  33.    if (this.registerErrorPageFilter) {
  34.       application.getSources().add(ErrorPageFilterConfiguration.class);
  35.    }
  36.     //启动Spring应用
  37.    return run(application);
  38. }
复制代码
7.Spring的应用就启动而且创建IOC容器
  1. public ConfigurableApplicationContext run(String... args) {
  2.    StopWatch stopWatch = new StopWatch();
  3.    stopWatch.start();
  4.    ConfigurableApplicationContext context = null;
  5.    FailureAnalyzers analyzers = null;
  6.    configureHeadlessProperty();
  7.    SpringApplicationRunListeners listeners = getRunListeners(args);
  8.    listeners.starting();
  9.    try {
  10.       ApplicationArguments applicationArguments = new DefaultApplicationArguments(
  11.             args);
  12.       ConfigurableEnvironment environment = prepareEnvironment(listeners,
  13.             applicationArguments);
  14.       Banner printedBanner = printBanner(environment);
  15.       context = createApplicationContext();
  16.       analyzers = new FailureAnalyzers(context);
  17.       prepareContext(context, environment, listeners, applicationArguments,
  18.             printedBanner);
  19.       
  20.        //刷新IOC容器
  21.       refreshContext(context);
  22.       afterRefresh(context, applicationArguments);
  23.       listeners.finished(context, null);
  24.       stopWatch.stop();
  25.       if (this.logStartupInfo) {
  26.          new StartupInfoLogger(this.mainApplicationClass)
  27.                .logStarted(getApplicationLog(), stopWatch);
  28.       }
  29.       return context;
  30.    }
  31.    catch (Throwable ex) {
  32.       handleRunFailure(context, listeners, analyzers, ex);
  33.       throw new IllegalStateException(ex);
  34.    }
  35. }
复制代码
结论:启动Servlet容器,再启动SpringBoot应用

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

石小疯

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表