SpringBoot——配置嵌入式 Servlet容器
更多内容,前往 IT-BLOG
一、如何定制和修改Servlet容器的相关配置
前言:SpringBoot 在Web 环境下,默认使用的是 Tomact 作为嵌入式的 Servlet容器;
☞ 我们也可以进入 port所属的对象中,发现其他可修改的参数等等,如下:
【2】编写一个 EmbeddedServletContainerCustomizer:嵌入式的 Servlet容器的定制器,来修改 Servlet容器的配置。其实1中的 ServerProperties也是实现了 EmbeddedServletContainerCustomizer。xxxCustomizer 帮组我们进行定制配置。
二、注册Servlet三大组件【Servlet、Filter、Listener】
由于 SpringBoot默认是以 jar包的方式启动嵌入的 Servlet容器来启动 SpringBoot的 web应用,没有 web.xml文件。注册三大组件的方式如下:
【1】通过 ServletRegistrationBean 注册自定义的 Servlet。
【2】通过 FilterRegistrationBean 注册拦截器 Filter。
【3】通过 ServletListenerRegistrationBean 注册自定义的 Listener。
三、使用其他 Servlet容器:Jetty(长连接引用)、Undertow(不支持JSP)
【1】我们在定制嵌入式的 Servlet容器时,会传入 ConfigurableEmbeddedServletContainer类,我们通过 Ctrl+T查看此可配置嵌入式类容器中可以配置 Tomcat、Jetty和Undertow。
四、嵌入式 Servlet容器自动配置原理
【1】EmbeddedServletContainerAutoConfiguration 类主要用来自动配置嵌入式的 Servlet容器。
【2】嵌入式的容器工厂:EmbeddedServletContainerFactory ,用来创建嵌入式的 Servlet容器。
☛ SpringBoot 再带了三种嵌入式的容器工厂,如下:
【3】EmbeddedServletContainer:嵌入式的容器,SpringBoot 为我们提供了三种不同的嵌入式容器,与工厂相互对应,如下:
【4】我们进入工厂类 TomcatEmbeddedServletContainerFactory发现,其实也是创建一个 Tomcat并配置其基本属性。
【5】用户自定义的 Servlet容器配置类和 SpringBoot 默认的 ServerProperties 配置类,都实现了EmbeddedServletContainerCustomizer 接口。到底是怎么实现的哪?其实是 SpringBoot 自动配置类中引入了后置处理器,如下:
☛ 进入后置处理器类中,重点看如下代码:
整理下步骤:【1】、SpringBoot根据pom.xml中导入的依赖,给容器中添加其对应的嵌入式的服务容器工厂类,例如默认的Tomcat工厂:EmbeddedServletContainerFactory【TomcatEmbeddedServletContainerFactory】
【2】、给容器中某个组件要创建对象就会触发后置处理器EmbeddedServletContainerCustomizerBeanPostProcessor,只要是嵌入式的Servlet容器工厂,后置处理器就会工作(默认的ServerProperties也是实现了此类接口的,所以肯定存在相关配置类)
【3】、后置处理器从容器中获取所有的EmbeddedServletContainerCustomizer,调用定制器的定制方法。
五、嵌入式Servlet容器启动原理
根据上述的流程,我们要研究Servlet容器的启动原理。其实就是研究什么时候创建嵌入式的容器工厂和何时获取嵌入式的容器并启动Tomcat。获取嵌入式的Servlet容器工厂的过程(在new TomcatEmbeddedServletContainerFactory()时打一个断电,查看过程):
【1】SpringBoot 应用启动运行 run() 方法。
【2】this.refreshContext(context) 方法:用来初始化 IOC容器,既创建 IOC容器对象并初始化IOC容器中的每一个组件。
【3】this.refresh(context):刷新刚才创建好的 IOC容器。
【4】this.onRefresh():web 的 IoC 容器重写了 onRefresh() 方法。
【5】this.createEmbeddedServletContainer():web的IOC容器会创建嵌入式的Servlet容器。
【6】获取嵌入式工厂后,便可从容器中获取 EmbeddedServletContainerFactory 的组件tomcatEmbeddedServletContainerFactory 来创建 Tomcat 对象,后置处理器就会触发获取所有的定制器来确定 Servlet容器的相关配置。
【7】通过嵌入式工厂获取嵌入式容器,如下:
● 嵌入式的Servlet容器创建并启动对象:
● 先启动嵌入式的Servlet容器,再将IOC容器中剩下没有创建的对象进行初始化,如下:
六、使用外置的Servlet容器
嵌入式Servlet容器的缺点:默认不支持JSP、优化和定制比较复杂。
外置Servlet容器:安装外部的Tomcat,步骤如下:
1)、必须创建一个war项目,需要手动创建目录(利用Idea快速创建)如下:
2)、将嵌入式的Tomcat指定为provide(Idea创建完后,会自动帮我们完成,但我们需要了解)
3)、需要编写一个SpringBootServletInitializer的子类,并调用configure方法:
4)、配置本地的Tomcat,并启动Tomcat即可。(此项目运行run()方法是不能启动项目的):需要设置名称和本地Tomcat的路径即可使用外部Servlet。
七、外置服务器的使用原理
☞ jar包:执行SpringBoot主类的main方法,启动并初始化IOC容器且创建嵌入式的Servlet容器。
☞ war包:启动服务器后调用SpringBootServletInitializer中的configure()方法,加载我们的SpringBoot应用并启动。
Servlet3.0规则:1)、服务器启动后,会创建当前web应用中包含的每个jar内的ServletContainerInitializer实例。
2)、ServletContainerInitializer的实现放在jar包的META-INF/services文件夹下(javax.servlet.ServletContainerInitializer:内容就是ServletContainerInitializer的全类名)
3)、可以使用@handlesTypes注解,在应用启动时加载我们需要的类。
流程:1)、启动Tomcat后,获取servlet.ServletContainerInitializer文件如下:其中的内容同下:
2)、进入SpringServletContainerInitializer发现此类将@HandlesTypes({WebApplicationInitializer.class})标注的所有这个类型的类都传入到onStartup方法中的Set<Class<?>>,并为这些类创建实例。
3)、每一个WebApplicationInitializer都调用自己的onStartup()方法。
4)、WebApplicationInitializer只是一个借口,其实现类主要有以下三个:SpringBootServletInitalizer正是SpringBoot给我们创建好的启动类,会被创建对象,并启动自身的onStartup()方法。
5)、执行onStartup()方法时,会调用createRootApplicationContext()方法来创建容器
6)、执行应用的run()方法,来启动Spring应用并创建IOC容器。