上一篇: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>