0

    Tomcat处理HTTP请求流程解析

    2023.07.26 | admin | 128次围观

    可以看到 server 已经正常启动,我们在网页上输入 127.0.0.1:9901, 可以看到已经能够正常返回了,是不是很简单呀。

    2、使用 Tomcat 处理HTTP请求

    从上面我们可以看到编写HTTP服务器其实是非常简单的,只需要先编写基于多线程的TCP服务,然后在一个TCP连接中读取HTTP请求,发送HTTP响应就可以了。

    但是,要编写一个完善的HTTP服务器,还要考虑更多东西例如:

    我们一直都在强调不要重复造轮子,Java发展了这么久处理TCP连接,解析HTTP协议这些底层工作早已有了现成的API。JavaEE提供的Servlet API,我们可以使用Servlet API编写自己的Servlet来处理HTTP请求,

    接下来我们看一个简单的例子

    import java.nio.charset.StandardCharsets;
    import java.io.*;
    import java.util.*;
    import java.net.*;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    // WebServlet注解表示这是一个Servlet,并映射到地址/:
    @WebServlet(urlPatterns = "/")
    public class HelloServlet extends HttpServlet {
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            // 设置响应类型:
            resp.setContentType("text/html");
            // 获取输出流:
            PrintWriter pw = resp.getWriter();
            String name = req.getParameter("name");
            // 写入响应:
            if (null == name) {
                pw.write("

    Hello, world!

    "); } else { pw.write("

    Hello, " + name + "!

    "); } // 最后不要忘记flush强制输出: pw.flush(); } }

    其中 Servlet API是一个jar包,我们需要通过Maven来引入它,才能正常编译。编写pom.xml文件如下

    
        4.0.0
        com.lzf.learnjava
        web-servlet-hello1
        war
        1.0-SNAPSHOT
        
            UTF-8
            UTF-8
            8
            8
            8
        
        
            
                javax.servlet
                javax.servlet-api
                4.0.0
                provided
            
        
        
            hello
        
    

    具体代码结构目录如下

    Mavean 打包出来的是war包, 需要运行的话得先启动Web服务器,而Web服务我们最常用的就是Tomcat。首先我们到官网下载Tomcat服务器,解压后

    Tomcat目录:

    bin:存放启动和关闭tomcat脚本 conf:存放不同的配置文件(server.xml和web.xml) doc:存放Tomcat文档 lib:存放Tomcat运行需要的库文件(JARS) logs:存放Tomcat执行时的LOG文件 webapps:Tomcat的主要Web发布目录(包括应用程序示例) work:存放jsp编译后产生的class文件

    Tomcat处理HTTP请求流程解析

    把hello.war复制到Tomcat的webapps目录下,Tomcat 默认监听的8080的端口请求的url在此服务器上找不到,可以通过修改 conf/server.xml -> Connector 里的 port 属性来改变监听端口。然后切换到bin目录,执行startup.sh或startup.bat启动Tomcat服务器

    网页上输入:9903/hello/?name=Qc ,成功访问!

    接下来我们来分析Tomcat 是如何处理一个HTTP请求的过程

    首先我们先了解Tomcat 的体系架构

    参考上面的图解释下:

    1.Server组件
       即服务器,每个tomcat程序启动后,就是一个server。
        
    2、Service组件
       一个Server可以包含多个Service,Service这是一种抽象的服务,它把连接器和处理引擎结合在一起。
    3、Connector组件:
       一个Service可以有多个Connector,Connector组件用于处理连接和并发。一般说来常见于server.xml
    中的连接器类型通常有4种:
      1) HTTP连接器 2) SSL连接器 3) AJP 1.3连接器 4) proxy连接器
      
    4、Engine组件:
       Engine是Servlet处理器的一个实例,即servlet引擎,其defaultHost属性是用来来为其定义一个接收所
    有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的:
       
    5、Host组件:
       位于Engine容器中,用于接收请求并进行相应处理的主机或虚拟主机.
       
      
      
      
      
      
      bbbtc.test
      
    6、Context组件:
       Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识tomcat实例中的一个Web应用程序
    

    了解了架构之后我们看请求过程

    1、用户打开浏览器输入地址,请求被发送到本机端口9903请求的url在此服务器上找不到,被在那里监听的Coyote HTTP/1.1 Connector获得。

    2、Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。

    3、Engine获得请求localhost:9903/hello/?name=Qc,匹配所有的虚拟主机Host。

    4、Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)名为localhost的Host获得请求/hello/?name=Qc,匹配它所拥有的所有的Context。 Host匹配到路径为/hello 的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)。

    5、在它的mapping table中寻找出对应的Servlet 处理数据。

    6、构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost().执行业务逻辑、数据存储等程序。

    7、Context把执行完之后的HttpServletResponse对象返回给Host。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论