zoukankan      html  css  js  c++  java
  • 【串线篇】spring boot使用外置的Servlet容器

    嵌入式Servlet容器:应用打成可执行的jar 优点:简单、便携;

    缺点:默认不支持JSP、优化定制比较复杂

    (使用定制器【ServerProperties/自定义EmbeddedServletContainerCustomizer】)

    (自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);

    那么如果要使用外置的servlet呢?

    应用war包的方式打包;

    外置的Servlet容器:外面安装Tomcat---

    步骤

    一、必须创建一个war项目;(利用idea创建好目录结构)

    二、将嵌入式的Tomcat指定为provided;

          <dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring‐boot‐starter‐tomcat</artifactId>

                <scope>provided</scope>

          </dependency>

    三、必须编写一个SpringBootServletInitializer的子类,并调用configure方法

    public  class  ServletInitializer  extends  SpringBootServletInitializer  {
    @Override
    protected  SpringApplicationBuilder  configure(SpringApplicationBuilder  application)  {
    //传入SpringBoot应用的主程序
    return  application.sources(SpringBoot04WebJspApplication.class);
    }
    }

    四、启动服务器就可以使用;

    原理

    jar包:执行SpringBoot主类的main方法,启动ioc容器,创建嵌入式的Servlet容器;

    war包:启动服务器,服务器启动SpringBoot应用【SpringBootServletInitializer】,启动ioc容器;

    servlet3.0(Spring注解版):

    8.2.4  Shared libraries / runtimes pluggability: 规则:

    1)、服务器启动(web应用启动)会创建当前web应用里面每一个jar包里面ServletContainerInitializer实例:

    2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为

    javax.servlet.ServletContainerInitializer的文件,内容就是ServletContainerInitializer的实现类的全类名

    3)、还可以使用@HandlesTypes,在应用启动的时候加载我们感兴趣的类;

    流程:

    1)、启动Tomcat

    2)、orgspringframeworkspring-web4.3.14.RELEASEspring-web-4.3.14.RELEASE.jar!META- INFservicesjavax.servlet.ServletContainerInitializer:

    Spring的web模块里面有这个文件:org.springframework.web.SpringServletContainerInitializer

    3)、SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有这个类型的类都传入到onStartup方法的Set>;为这些WebApplicationInitializer类型的类创建实例;

    4)、每一个WebApplicationInitializer都调用自己的onStartup;

    五、相当于我们的SpringBootServletInitializer的类会被创建对象,并执行onStartup方法

    六、SpringBootServletInitializer实例执行onStartup的时候会createRootApplicationContext;创建容器

    protected  WebApplicationContext  createRootApplicationContext(
        ServletContext  servletContext)  {
        //1、创建SpringApplicationBuilder
        SpringApplicationBuilder  builder  =  createSpringApplicationBuilder();
        StandardServletEnvironment  environment  =  new  StandardServletEnvironment();
        environment.initPropertySources(servletContext,  null);
        builder.environment(environment);
        builder.main(getClass());
        ApplicationContext  parent  =  getExistingRootWebApplicationContext(servletContext);
        if (parent != null) {
        this.logger.info("Root  context  already  created  (using  as  parent).");
        servletContext.setAttribute(
        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,  null);
        builder.initializers(new  ParentContextApplicationContextInitializer(parent)); 15    }
        builder.initializers(
        new  ServletContextApplicationContextInitializer(servletContext));
        builder.contextClass(AnnotationConfigEmbeddedWebApplicationContext.class); 
        //调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来
        builder = configure(builder); 22
            //使用builder创建一个Spring应用
            SpringApplication  application  =  builder.build();
            if  (application.getSources().isEmpty()  &&  AnnotationUtils
            .findAnnotation(getClass(),  Configuration.class)  !=  null)  {
            application.getSources().add(getClass());
            }
            Assert.state(!application.getSources().isEmpty(),
            "No  SpringApplication  sources  have  been  defined.  Either  override  the  "
            +  "configure  method  or  add  an  @Configuration  annotation");
            // Ensure error pages are registered
            if (this.registerErrorPageFilter) {
            application.getSources().add(ErrorPageFilterConfiguration.class);
            }
            //启动Spring应用
            return run(application);
        }    

    七、Spring的应用就启动并且创建IOC容器

        public  ConfigurableApplicationContext  run(String...  args)  {
        StopWatch  stopWatch  =  new  StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext  context  =  null;
        FailureAnalyzers  analyzers  =  null;
        configureHeadlessProperty();
        SpringApplicationRunListeners  listeners  =  getRunListeners(args);
        listeners.starting();
    try {
    
    ApplicationArguments  applicationArguments  =  new  DefaultApplicationArguments(
    args);
    ConfigurableEnvironment  environment  =  prepareEnvironment(listeners, applicationArguments);
    Banner  printedBanner  =  printBanner(environment); context  =  createApplicationContext();
    analyzers  =  new  FailureAnalyzers(context);
    prepareContext(context,  environment,  listeners,  applicationArguments, printedBanner);
    
    //刷新IOC容器 refreshContext(context);
    afterRefresh(context,  applicationArguments); listeners.finished(context, null); stopWatch.stop();
    if  (this.logStartupInfo)  {
    new  StartupInfoLogger(this.mainApplicationClass)
    .logStarted(getApplicationLog(),  stopWatch);
    }
    return context;
    }
    catch  (Throwable  ex)  {
    handleRunFailure(context,  listeners,  analyzers,  ex); throw  new  IllegalStateException(ex);
    }
    }

    启动Servlet容器,再启动SpringBoot应用

  • 相关阅读:
    【flink】flink1.12 application mode on k8s
    【spark】读取高版本的elasticsearch
    [spark] spark2.4运行在k8s
    【spring】springboot使用jpa集成elasticsearch7.0
    【spark】cache不一定使用的场景
    JDK源码分析
    排序算法
    EagleEye鹰眼原理分析
    需求分析模版
    记一次线上事故内存泄漏:java.lang.OutOfMemoryError: unable to create new native thread
  • 原文地址:https://www.cnblogs.com/yanl55555/p/12091860.html
Copyright © 2011-2022 走看看