springboot-嵌入式Servlet容器(Tomcat)源码分析以及容器切换
目錄
一、springboot的嵌入式Servlet容器(tomcat)
1.原理
2.源碼
(1)ServletWebServerApplicationContext的createWebServer方法
(2)獲取tomcat的webServer
(3)tomcat的啟動方法
二、切換嵌入式Servlet容器
1.排除tomcat,添加undertow
2.啟動時就會使用undertow(還是建議使用tomcat)
一、springboot的嵌入式Servlet容器(tomcat)
1.原理
(1)SpringBoot應用啟動發現當前是Web應用。(web場景包starter會導入tomcat)
(2)web應用會創建一個web版的ioc容器 ServletWebServerApplicationContext。
(3)ServletWebServerApplicationContext??啟動的時候尋找 ServletWebServerFactory(Servlet 的web服務器工廠--->?生產Servlet 的web服務器)。
(4)SpringBoot底層默認有很多的WebServer工廠;TomcatServletWebServerFactory, JettyServletWebServerFactory, UndertowServletWebServerFactory。
(5)SpringBoot底層直接會有一個自動配置類。ServletWebServerFactoryAutoConfiguration
(6)ServletWebServerFactoryAutoConfiguration導入了ServletWebServerFactoryConfiguration(配置類)
(7)ServletWebServerFactoryConfiguration 配置類 根據動態判斷系統中到底導入了那個Web服務器的包。(默認是web-starter導入tomcat包),容器中就有TomcatServletWebServerFactory。
(8)TomcatServletWebServerFactory 創建出Tomcat服務器并啟動;TomcatWebServer 的構造器擁有初始化方法initialize---會調用this.tomcat.start();
(9)內嵌服務器,就是手動把啟動服務器的代碼調用(前提是tomcat核心jar包存在)
2.源碼
(1)ServletWebServerApplicationContext的createWebServer方法
// org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer private void createWebServer() {WebServer webServer = this.webServer; ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) {// 獲取ServletWebServerFactory,默認是tomcat的ServletWebServerFactory factory = getWebServerFactory();// 通過ServletWebServerFactory創建webServerthis.webServer = factory.getWebServer(getSelfInitializer());getBeanFactory().registerSingleton("webServerGracefulShutdown",new WebServerGracefulShutdownLifecycle(this.webServer));getBeanFactory().registerSingleton("webServerStartStop",new WebServerStartStopLifecycle(this, this.webServer));}else if (servletContext != null) {try {getSelfInitializer().onStartup(servletContext);}catch (ServletException ex) {throw new ApplicationContextException("Cannot initialize servlet context", ex);}}// 啟動tomcatinitPropertySources(); }(2)獲取tomcat的webServer
// org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer @Override public WebServer getWebServer(ServletContextInitializer... initializers) {if (this.disableMBeanRegistry) {Registry.disableRegistry();}Tomcat tomcat = new Tomcat();File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());Connector connector = new Connector(this.protocol);connector.setThrowOnFailure(true);tomcat.getService().addConnector(connector);customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);configureEngine(tomcat.getEngine());for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);}prepareContext(tomcat.getHost(), initializers);return getTomcatWebServer(tomcat); }(3)tomcat的啟動方法
tomcat初始的時候就會調用start。
// org.springframework.boot.web.embedded.tomcat.TomcatWebServer#start @Override public void start() throws WebServerException {synchronized (this.monitor) {if (this.started) {return;}try {addPreviouslyRemovedConnectors();Connector connector = this.tomcat.getConnector();if (connector != null && this.autoStart) {performDeferredLoadOnStartup();}checkThatConnectorsHaveStarted();this.started = true;logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"+ getContextPath() + "'");}catch (ConnectorStartFailedException ex) {stopSilently();throw ex;}catch (Exception ex) {PortInUseException.throwIfPortBindingException(ex, () -> this.tomcat.getConnector().getPort());throw new WebServerException("Unable to start embedded Tomcat server", ex);}finally {Context context = findContext();ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());}} }二、切換嵌入式Servlet容器
1.排除tomcat,添加undertow
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions> </dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId> </dependency>2.啟動時就會使用undertow(還是建議使用tomcat)
?
總結
以上是生活随笔為你收集整理的springboot-嵌入式Servlet容器(Tomcat)源码分析以及容器切换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: springboot-拦截器的实现、执行
- 下一篇: springboot使用原生servle