上一篇:Tomcat8源碼分析-啓動流程-start方法html
此篇主要將Tomcat8從接收請求處處理請求的時序圖畫出來,並用文字描述一下主要流程java
圖片有點大,須要點開了放大看web
文字描述流程以前先提示以下兩點:
1.Acceptor、Poller、SocketProcessor都是NioEndpoint的內部類apache
2.Tomcat不必定只有NioEndpoint還有Nio2Endpoint AprEndpoint,只是常規的請求和默認都使用的是http和nio,因此在時序圖中就用NioEndpoint了tomcat
Acceptor負責接收發起的請求,通過NioEndpoint和Poller將socket最終包裝爲一個PollerEvent放入到SynchronizedQueue同步隊列當中,接着繼續等待新的請求到底重複前面的步驟app
Poller循環判斷同步隊列中是否有問題處理的Event,若是有則使用WindowsSelectorImpl讀取socket,將socket中的attachment添加到SocketProcessor( implements runnable),使用線程池啓動SocketProcessorwebapp
SocketProcessor通過一層層調用直到按照StandardEngine-StandardHost-StandardContext-StandardWrapper順序執行它們的Pipeline.First Valve,最後由StandardWrapperValve執行Servlet的加載,加載完後會調用Servlet的init方法,而後由ApplicationFilterChain調用HttpServlet的service,進而調用到本身的Servlet中的doXxx方法socket
如圖:jsp
CoyoteAdapter裏面的postParseRequest方法包含了很是重要的根據path找到對應Servlet的邏輯,具體規則以下:maven
先精確匹配-通配符匹配-後綴名匹配(默認有jsp和jspx,這也是爲何能夠處理jsp的緣由)-Welcome資源匹配-前面都沒匹配到就是DefaultServlet
匹配成功以後,StandardWrapperValve對應的StandardWrapper.servlet纔會是咱們想要的,才能實現真正的業務調用。
1.接收請求參數的流程仍是比較簡單清晰,裏面使用了模板方法模式、責任鏈模式(如Pipeline的執行)、門面模式等。
2.裏面發現了兩種擴展點
3.要想快速搞清楚調用過程,建議直接在自定義的Servlet方法中加斷點,要達到這個效果須要新建的web應用和tomcat是在同一個項目中,方式以下:
先看看idea中的目錄結構
圖中還有一處沒有標記出來:就是在idea中選擇新建了一個maven的web-module以後是沒有源碼目錄的,我是在main下新建的一個java目錄,而後右鍵標記爲source root,再在目錄下編寫Servlet的
Servlet代碼
package com.jv.tomcat; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class TestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("content-type", "text/html;charset=UTF-8"); resp.setCharacterEncoding("UTF-8"); System.out.println("My TestServlet doGet"); resp.getWriter().print("<html><body><h1>My TestServlet doGet</h1></body></html>"); } }
看看pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>apache-tomcat-8</artifactId> <groupId>gxf</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>testweb</artifactId> <packaging>war</packaging> <name>testweb</name> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 配置了這個依賴,須要將tomcat源碼install到本地maven倉庫,不然會提示依賴不存在 --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-8</artifactId> <version>8.5</version> </dependency> </dependencies> <build> <finalName>testweb</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <!-- 編譯的時候將class文件輸出到配置目錄下,由於打war包的時候會從整個目錄複製class文件 --> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> <outputDirectory>F:\projects\own\tomcat-8.5.49\testweb\src\main\webapp\WEB-INF\classes</outputDirectory> </configuration> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <!-- 打war包,並將war包複製到tomcat的工做目錄下 --> <plugin> <artifactId>maven-war-plugin</artifactId> <configuration> <archiveClasses>true</archiveClasses> <outputDirectory>F:\projects\own\tomcat-8.5.49\deploy-test\webapps</outputDirectory> </configuration> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>