问题概述

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

优点:简单、便携;

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

如使用jsp:

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

新建项目



IDEA中配置Webapp文件



配置web.xml文件



配置tomcat



测试

目录结构



在application.properties文件中配置springmvc的视图解析:

spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp

测试:

步骤

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

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

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

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

public class ServletInitializer extends SpringBootServletInitializer {

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

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

原理

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

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

servlet3.0规范:(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)、\org\springframework\spring-web\5.1.9.RELEASE\spring-web-5.1.9.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer

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

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

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


点进WebApplicationInitializer查看:



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

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

protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
//1、创建SpringApplicationBuilder
SpringApplicationBuilder 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 registered
if (this.registerErrorPageFilter) {
application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
}
//启动Spring应用
return run(application);
}

7)、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);
}
}

最新文章

  1. Spark源码编译并在YARN上运行WordCount实例
  2. mysql 常用sql
  3. ubuntu 搭建maven库 2.14.2-01并配置离线索引文件
  4. PHP操作Excel – PHPExcel 基本用法详解
  5. Repeater的ItemCreated和ItemDataBind的区别
  6. Robot Framework安装
  7. ajax请求参数为中文乱码的情况
  8. 收集的jquery插件
  9. [LeetCode]题解(python):084-Largest Rectangle in Histogram
  10. 搭建App主流框架_纯代码搭建(OC)
  11. 解决无法打开myeclipse--&gt;“The default workspace&#39;D: /myeclipse spaceis in use or cannot be created. Please choose a different one”
  12. 异常捕获try----catch
  13. SQL Server 2016新特性:列存储索引新特性
  14. P4512 【模板】多项式除法
  15. HTML学习笔记07-头部
  16. linux系统上项目部署
  17. 使用&lt;c:set&gt;标签配置项目路径
  18. virgo-tomcat-server的生产环境线上配置与管理
  19. php实现AES/CBC/PKCS5Padding加密解密(又叫:对称加密)
  20. 5、Docker架构和底层技术

热门文章

  1. 区别 |DCL |DDL |DML |DQL
  2. TopCoder[TCO2016 Round 1A]:EllysTree(1000)
  3. delphi 备注一些函数
  4. [JZOJ 100025] 棋盘
  5. mysql中的Date日期格式的问题:只有日期没有时间及格式化时间
  6. LeetCode 183. Customers Who Never Order (从不订购的客户)
  7. D.Country Meow 最小球覆盖 三分套三分套三分 &amp;&amp; 模拟退火
  8. Dijkstra with priority queue 分类: ACM TYPE 2015-07-23 20:12 4人阅读 评论(0) 收藏
  9. 20140421 常量指针与指针常量; const指针; reinterpret_cast ;const_cast作用
  10. scala中闭包的使用