Spring Boot使用外部的Servlet容器支持JSP页面 :

使用

嵌入式Servlet容器:应用打成可执行的jar

优点:简单、便携;

缺点:默认不支持JSP、优化定制比较复杂(使用定制器【ServerProperties、自定义EmbeddedServletContainerCustomizer】,自己编写嵌入式Servlet容器的创建工厂【EmbeddedServletContainerFactory】);

AgShnO.png

注意打包为War包

AgSLgP.png

外置的Servlet容器:外面安装Tomcat—-应用war包的方式打包;

编写一个SpringBootServletInitializer的子类,并调用configure方法

12345678
public class ServletInitializer extends SpringBootServletInitializer{

@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application){//传入SpringBoot应用的主程序return application.sources(SpringBoot04WebJspApplication.class);}}

启动服务器就可以使用;

但是SpringBoot默认的嵌入容器Tomcat不支持JSP,因此我们需要用外置的Tomcat来打包该项目

AgmXJf.png

Agnmy4.png

AgnMwR.png

Agnd0A.png

原理

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

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

在servlet3.0中的第8.3 JSP container pluggability章节中

文档链接

The ServletContainerInitializer class is looked up via the jar services API. For each application, an instance of the ServletContainerInitializer is created by the container at application startup time. The framework providing an
implementation of the ServletContainerInitializer MUST bundle in the META-INF/services directory of the jar file a file called javax.servlet.ServletContainerInitializer, as per the jar services API, that points to the implementation class of the ServletContainerInitializer.In addition to the ServletContainerInitializer we also have an annotation -HandlesTypes. The HandlesTypes annotation on the implementation of the ServletContainerInitializer is used to express interest in classes that may have annotations (type, method or field level annotations) specified in the value of the HandlesTypes or if it extends / implements one those classes anywhere in the class’ super types. The HandlesTypes annotation is applied irrespective of the setting of metadata-complete.

解读:

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

​ 2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下,有一个名为javax.servlet.ServletContainerInitializer的文件,内容就是ServletContainerInitializer的实现类的全类名

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

流程

1)、启动Tomcat

2)、org/springframework/spring-web/5.1.5.RELEASE/spring-web-5.1.5.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;

123
public interface WebApplicationInitializer{void onStartup(ServletContext servletContext) throws ServletException;}

AgYWFg.png

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

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

1234567891011121314151617181920212223242526272829303132333435
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext){//1、创建SpringApplicationBuilderSpringApplicationBuilder builder = createSpringApplicationBuilder();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));}builder.initializers(new ServletContextApplicationContextInitializer(servletContext));builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);                 //调用configure方法,子类重写了这个方法,将SpringBoot的主程序类传入了进来builder = configure(builder);

builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext));//使用builder创建一个Spring应用SpringApplication application = builder.build();if (application.getAllSources().isEmpty() && AnnotationUtils.findAnnotation(getClass(), Configuration.class) != null) {application.addPrimarySources(Collections.singleton(getClass()));}Assert.state(!application.getAllSources().isEmpty(),"No SpringApplication sources have been defined. Either override the "+ "configure method or add an @Configuration annotation");// Ensure error pages are registeredif (this.registerErrorPageFilter) {application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));}//启动Spring应用return run(application);}

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

1234567891011121314
protected WebApplicationContext run(SpringApplication application){//点击进入run方法return (WebApplicationContext) application.run();}

private ApplicationContext getExistingRootWebApplicationContext(ServletContext servletContext){Object context = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);if (context instanceof ApplicationContext) {return (ApplicationContext) context;}return null;}

点击进入run方法

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
public ConfigurableApplicationContext run(String... args){StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);context = createApplicationContext();exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);prepareContext(context, environment, listeners, applicationArguments,printedBanner);

//刷新IOC容器refreshContext(context);afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}listeners.started(context);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}

try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;}

SpringBoot使用外置的Servlet容器相关推荐

  1. SpringBoot之配置嵌入式Servlet容器

    1.概述 文章目录 1.概述 2.如何修改SpringBoot的默认配置 3.定制和修改Servlet容器的相关配置 4.注册Servlet三大组件 5.替换为其他嵌入式Servlet容器 6.嵌入式 ...

  2. springboot(七) 配置嵌入式Servlet容器

    github代码地址:https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service ...

  3. SpringBoot配置嵌入式Servlet容器

    SpringBoot默认使用的是Tomcat作为嵌入式的Servlet容器,那么肯定会和外置的Tomcat有区别,那么就这些区别来谈一谈SpringBoot中对于容器的一些配置操作 如何定制和修改Se ...

  4. SpringBoot 配置嵌入式Servlet容器(tomcat,jetty,undertow)

    SpringBoot 默认打包方式为jar包,且可以自启动,就是因为它内嵌了Servlet容器. SpringBoot 默认使用嵌入式Servlet容器,SpringBoot 2.2.5 默认是 To ...

  5. SpringBoot源码分析之内置Servlet容器

    原文链接:http://fangjian0423.github.io/2017/05/22/springboot-embedded-servlet-container/ SpringBoot内置了Se ...

  6. servlet容器_SpringBoot是否内置了Servlet容器?

    SpringBoot是否内置了Servlet容器? SpringBoot内置了Servlet容器,这样项目的发布.部署就不需要额外的Servlet容器,直接启动jar包即可.SpringBoot官方文 ...

  7. servlet如何使用session把用户的手机号修改_SpringBoot源码学习系列之嵌入式Servlet容器...

    1.前言简单介绍 SpringBoot的自动配置就是SpringBoot的精髓所在:对于SpringBoot项目是不需要配置Tomcat.jetty等等Servlet容器,直接启动applicatio ...

  8. SpringBoot 嵌入式Servlet容器

    一.嵌入式Servlet容器 切换嵌入式Servlet容器 默认支持的webServer :Tomcat, Jetty, or Undertow ServletWebServerApplication ...

  9. 六十七、SpringBoot嵌入式的Servlet容器和创建war项目

    @Author:Runsen 来源:尚硅谷 下面建议读者学习尚硅谷的B站的SpringBoot视频,我是学雷丰阳视频入门的. 具体链接如下:B站尚硅谷SpringBoot教程 文章目录 三种嵌入式容器 ...

最新文章

  1. mysql中文无法显示
  2. 测试类图Head First 设计模式 (九) 迭代器与组合模式(Iterator Composite pattern) C++实现...
  3. PCA主成分分析以及Python实现(阅读笔记)
  4. 数据挖掘十大经典算法之——C4.5 算法
  5. 0322 第一天 心得体会
  6. 创建时间指定日期 java,Java避坑之如何创建指定时间Date对象
  7. Event Organization Site - To be published on 4th August
  8. 面向对象编程:包,继承,多态,抽象类,接口
  9. coreldraw怎么画转弯箭头_新交规出炉,这样转弯会被扣8分罚款300,又有7.3万车主因此被罚!...
  10. HTML网页头部小图标
  11. 名义利率、实际利率、名义贴现率
  12. 感应加热计算机仿真软件,一种新型感应加热电源调功方式的研究与计算机仿真...
  13. 倒计时最后3天,抢永久0服务费微信直连商户
  14. 机器学习常见任务类型
  15. 动力节点-crm-项目笔记(待完善)
  16. 实时时钟模块RX-8010SJ
  17. 深度学习(一)多层感知器MLP/人工神经网络ANN
  18. 【手机建站】Android Termux+cpolar内网穿透,搭建外网可以访问的网站
  19. 安防监控之软硬件环境分析和通信结构体定义
  20. [操作系统] 操作系统真相还原读书笔记三:MBR加载loader到内存并跳转到loader执行

热门文章

  1. python如何调用xpath_Python案例:使用XPath的爬虫
  2. jtessboxeditorfx 界面显示不出来_不需要发酵,自制家庭版健康小油条,不会失败的配方...
  3. 凡人和神学习和使用软件的七个层次
  4. keep-alive使用笔记
  5. php大文件下載,使用apache/nginx x-sendFile模塊替換
  6. spring_装配Bean
  7. ubuntu下安装 memecache
  8. RTT的线程同步篇——异常管理
  9. RTT——IO设备管理篇·基本概念理解
  10. 线性表——顺序表的应用