您好,登錄后才能下訂單哦!
這篇文章主要介紹了Tomcat的工作原理和處理請求流程是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Tomcat的工作原理和處理請求流程是什么文章都會有所收獲,下面我們一起來看看吧。
Tomcat 連接器框架——Coyote
一、監聽網絡端口,接收和響應網絡請求。
二、網絡字節流處理。將收到的網絡字節流轉換成 Tomcat Request 再轉成標準的 ServletRequest 給容器,同時將容器傳來的 ServletResponse 轉成 Tomcat Response 再轉成網絡字節流。
為滿足連接器的兩個核心功能,我們需要一個通訊端點來監聽端口;需要一個處理器來處理網絡字節流;最后還需要一個適配器將處理后的結果轉成容器需要的結構。
對應的源碼包路徑 org.apache.coyote 。對應的結構圖如下
Tomcat 容器框架——Catalina
每個 Service 會包含一個容器。容器由一個引擎可以管理多個虛擬主機。每個虛擬主機可以管理多個 Web 應用。每個 Web 應用會有多個 Servlet 包裝器。Engine、Host、Context 和 Wrapper,四個容器之間屬于父子關系。
對應的源碼包路徑 org.apache.coyote 。對應的結構圖如下
容器的請求處理過程就是在 Engine、Host、Context 和 Wrapper 這四個容器之間層層調用,最后在 Servlet 中執行對應的業務邏輯。各容器都會有一個通道 Pipeline,每個通道上都會有一個 Basic Valve(如StandardEngineValve), 類似一個閘門用來處理 Request 和 Response 。其流程圖如下。
上面的知識點已經零零碎碎地介紹了一個 Tomcat 是如何處理一個請求。簡單理解就是連接器的處理流程 + 容器的處理流程 = Tomcat 處理流程。哈!那么問題來了,Tomcat 是如何通過請求路徑找到對應的虛擬站點?是如何找到對應的 Servlet 呢?
這里需要引入一個上面沒有介紹的組件 Mapper。顧名思義,其作用是提供請求路徑的路由映射。根據請求URL地址匹配是由哪個容器來處理。其中每個容器都會它自己對應的Mapper,如 MappedHost。不知道大家有沒有回憶起被 Mapper class not found 支配的恐懼。在以前,每寫一個完整的功能,都需要在 web.xml 配置映射規則,當文件越來越龐大的時候,各個問題隨著也會出現
打開 tomcat/conf 目錄下的 server.xml 文件來分析一個http://localhost:8080/docs/api 請求。
第一步:連接器監聽的端口是8080。由于請求的端口和監聽的端口一致,連接器接受了該請求。
第二步:因為引擎的默認虛擬主機是 localhost,并且虛擬主機的目錄是webapps。所以請求找到了 tomcat/webapps 目錄。
第三步:解析的 docs 是 web 程序的應用名,也就是 context。此時請求繼續從 webapps 目錄下找 docs 目錄。有的時候我們也會把應用名省略。
第四步:解析的 api 是具體的業務邏輯地址。此時需要從 docs/WEB-INF/web.xml 中找映射關系,最后調用具體的函數。
<?xml version="1.0"> SpringBoot 如何啟動內嵌的 TomcatSpringBoot 一鍵啟動服務的功能,讓有很多剛入社會的朋友都忘記 Tomcat 是啥。隨著硬件的性能越來越高,普通中小項目都可以直接用內置 Tomcat 啟動。但是有些大一點的項目可能會用到 Tomcat 集群和調優,內置的 Tomcat 就不一定能滿足需求了。我們先從源碼中分析 SpringBoot 是如何啟動 Tomcat,以下是 SpringBoot 2.x 的代碼。代碼從 main 方法開始,執行 run 方法啟動項目。SpringApplication.run 從 run 方法點進去,找到刷新應用上下文的方法。this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context); this.afterRefresh(context, applicationArguments); 從 refreshContext 方法點進去,找 refresh 方法。并一層層往上找其父類的方法。this.refresh(context); 在 AbstractApplicationContext 類的 refresh 方法中,有一行調用子容器刷新的邏輯。this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); 從 onRefresh 方法點進去,找到 ServletWebServerApplicationContext 的實現方法。在這里終于看到了希望。protected void onRefresh() { super.onRefresh(); try { this.createWebServer(); } catch (Throwable var2) { throw new ApplicationContextException("Unable to start web server", var2); } } 從 createWebServer 方法點進去,找到從工廠類中獲取 WebServer的代碼。if (webServer == null && servletContext == null) { ServletWebServerFactory factory = this.getWebServerFactory(); // 獲取 web server this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); } else if (servletContext != null) { try { // 啟動 web server this.getSelfInitializer().onStartup(servletContext); } catch (ServletException var4) { throw new ApplicationContextException("Cannot initialize servlet context", var4); } } 從 getWebServer 方法點進去,找到 TomcatServletWebServerFactory 的實現方法,與之對應的還有 Jetty 和 Undertow。這里配置了基本的連接器、引擎、虛擬站點等配置。public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new Tomcat(); File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); this.customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); this.configureEngine(tomcat.getEngine()); Iterator var5 = this.additionalTomcatConnectors.iterator(); while(var5.hasNext()) { Connector additionalConnector = (Connector)var5.next(); tomcat.getService().addConnector(additionalConnector); } this.prepareContext(tomcat.getHost(), initializers); return this.getTomcatWebServer(tomcat); } 服務啟動后會打印日志o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8900 (http) o.apache.catalina.core.StandardService : Starting service [Tomcat] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.34 o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal ... o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 16858 ms 我感覺我好像發現為什么比較牛的公司都會問到技術的底層源碼了,因為在看源碼的過程中是真的很有意思,并且能夠發現很多的問題,而且真的是考驗邏輯思維和耐心,我這看個tomcat源碼,一天的時候就那么過去了,還沒整完,這還是我以為我對tomcat已經非常熟悉的前提下了,哈哈哈哈,關注我,后面有時間再慢慢更新吧 最后給大家介紹一份文檔,這也是我在解析tomcat過程中參考最多的書籍,內部的知識基本涵蓋了tomcat的相關內容,從架構設計到配置到集群到性能優化和擴展等,全方位解析tomcat,有需要的朋友可以關注+轉發后,私信“源碼”即可查看獲取方式 tomcat架構 tomcat配置管理 tomcat安全 tomcat調優 tomcat附加功能 篇幅原因,只展示這一部分,有需要更多Java相關學習文檔,視頻的,關注我,后臺私信“資料”即可獲取
關于“Tomcat的工作原理和處理請求流程是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Tomcat的工作原理和處理請求流程是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。