web应用学习_Spring Boot外置Tomcat启动

 

https://www.cnblogs.com/developerxiaofeng/p/9081689.html

jar包和war包启动区别:

  • jar包: 执行SpringBootApplication的run方法,启动IOC容器,然后创建嵌入式Servlet容器
  • war包:  先是启动Servlet服务器,服务器启动Springboot应用(springBootServletInitizer),然后启动IOC容器

正常springboot项目在创建的时候是会生成启动类的,这个类启动的是内置的tomcat容器,但是我们也是可以用外部的容器,这个时候我们发现有一个问题就是,我们配置的时候好像少了一个web.xml文件,这个是在spring+springmvc时代的配置文件,但是在springboot中是没有这个文件的,但是功能上来说我们不能丢弃这,所以才需要继承SpringBootServletInitializer这个类来替代web.xml的功能。(原文链接:https://blog.csdn.net/hy_coming/article/details/103307000、https://blog.csdn.net/wey1234567/article/details/95045388)

 

Spring Boot项目有两种部署方式,1、Spring Boot 内置Tomcat启动(jar包);2、Spring Boot外置Tomcat启动(war包)

Servlet 3.0+规定:

  1. 服务器启动(web应用启动),会创建当前web应用里面所有jar包里面的ServletContainerlnitializer实例
  2. ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下
  3. 还可以使用@HandlesTypes注解,在应用启动的时候加载指定的类。

外部Tomcat流程以及原理

  ①  启动Tomcat

  ②  根据上述描述的Servlet3.0+规则,可以在Spring的web模块里面找到有个文件名为javax.servlet.ServletContainerInitializer的文件,而文件的内容为org.springframework.web.SpringServletContainerInitializer,用于加载SpringServletContainerInitializer类。

  ③看看SpringServletContainerInitializer定义。SpringServletContainerInitializer将@HandlesTypes(WebApplicationInitializer.class)标注的所有WebApplicationInitializer这个类型的类都传入到onStartup方法的Set参数中,并通过反射为这些WebApplicationInitializer类型的类创建实例;

  ④  方法最后,每一个WebApplicationInitilizer实现调用自己onstartup方法

  ⑤  而WebApplicationInitializer有个抽象实现类SpringBootServletInitializer(记住我们继承了该抽象类),则会调用每一个WebApplicationInitializer实例(包括SpringBootServletInitializer)的onStartup方法:

       SpringBootServletInitializer实例执行onStartup方法的时候会通过createRootApplicationContext方法来执行run方法,接下来的过程就同以jar包形式启动的应用的run过程一样了,在内部会创建IOC容器并返回,只是以war包形式的应用在创建IOC容器过程中不再创建Servlet容器了。

 

----------------------------------------

 

web容器(例如Tomcat)启动时为提供给第三方组件做一些初始化工作的机会,例如注册servlet或者filters等,servlet规范中通过ServletContainerInitializer实现此功能。

每个框架要使用ServletContainerInitializer,就必须在对应的jar包的META-INF/services目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。

一般伴随着ServletContainerInitializer一起使用的还有HandlesTypes注解,通过HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup()方法作为参数传入。

Tomcat容器的ServletContainerInitializer机制的实现,主要交由Context容器ContextConfig监听器共同实现:首先通过ContextConfig监听器遍历每个jar包或web根目录的META-INF/services/javax.servlet.ServletContainerInitializer文件,根据读到的类路径通过反射完成这些ServletContainerInitializer的实例化;然后再分别将实例化好的ServletContainerInitializer设置进Context容器中;最后Context容器启动时分别调用所有ServletContainerInitializer对象的onStartup方法,并将感兴趣的类作为参数传入。

 

/org/springframework/spring-web/5.1.10.RELEASE/spring-web-5.1.10.RELEASE.jar!/META-INF/services/javax.servlet.ServletContainerInitializer中指定了org.springframework.web.SpringServletContainerInitializer这个类,即在Tomcat的Context容器启动的时候会调用SpringServletContainerInitializer这个类的onStartup()方法,并将WebApplicationInitializer这个类的实现类作为参数传入。

onStartup(@Nullable Set> webAppInitializerClasses, ServletContext servletContext){}方法中,先判断webAppInitializerClasses这个Set是否为空。如果不为空的话,找到这个set中不是接口、不是抽象类、并且是WebApplicationInitializer接口的实现类,将它们保存到list中。当这个list为空的时候,抛出异常。不为空的话就按照一定的顺序排序,并将它们按照一定的顺序实例化。调用其onStartup方法执行。

WebApplicationInitializer.class的几个实现类:(这几个好像都是抽象类啊,怎么理解呢?是这样的,比如SpringBoot项目选择外置Tomcat启动,则需要继承SpringBootServletInitializer,tomcat根据上述Servlet3.0+规则来启动这个应用)

  • AbstractContextLoaderInitializer (org.springframework.web.context) 
  • AbstractDispatcherServletInitializer (org.springframework.web.servlet.support) (配置DispatcherServlet初始化器)
  • AbstractAnnotationConfigDispatcherServletInitializer (org.springframework.web.servlet.support) (注解方式配置的DispatcherServlet初始化器)
  • AbstractReactiveWebInitializer
  • JerseyWebApplicationInitializer
  • SpringBootServletInitializer

web应用学习_Spring Boot外置Tomcat启动_第1张图片
————————————————
版权声明:本文为CSDN博主「yangliuhbhd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yangliuhbhd/article/details/80803464

 

 

在 Spring MVC 中存在两种应用上下文:DispatcherServlet 创建的上下文拦截器 ContextLoaderListener 创建的上下文

  • DispatcherServlet:加载包含 web 组件的 bean,比如 controllers,view resolvers 和 hanlder mappings。
  • ContextLoaderListener:加载其他 bean,通常是一些中间层和数据层的组件(比如数据库配置 bean 等)。

web应用学习_Spring Boot外置Tomcat启动_第2张图片

https://docs.spring.io/spring-framework/docs/5.0.2.RELEASE/spring-framework-reference/web.html#mvc-servlet-context-hierarchy

在 AbstractAnnotationConfigDispatcherServletInitializer 中 DispatcherServlet 和 ContextLoaderListener 都会被创建,而基类中的方法就可用来创建不同的应用上下文:

getServletConfigClasses():定义 DispatcherServlet 应用上下文中的 beans

getRootConfigClasses():定义拦截器 ContextLoaderListener 应用上下文中的 beans

Note:为了使用 AbstractAnnotationConfigDispatcherServletInitializer 必须保证 web 服务器支持 Servlet 3.0 标准(如 tomcat 7 或更高版本) 。
————————————————
版权声明:本文为CSDN博主「yangliuhbhd」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yangliuhbhd/article/details/80803464

 

 

Spring只是一个框架,用来简化开发。

如果是web应用,则涉及到servlet、servlet容器等等,可以使用Spring MVC框架快速开发,需要将web应用部署到Tomcat中进而提供服务(当然Tomcat也是跑在JVM上的)。

如果不是是web应用,肯定不涉及Tomcat和Spring MVC等web框架,但是可以有Spring框架来处理bean之间的依赖关系等等,应用应该是直接跑在JVM上的。

----------------------------------------

--------------------------------

 

你可能感兴趣的:(Dive,into,Spring)