Tomcat的架构图

 
              图三:Tomcat Server处理一个HTTP请求的过程

处理HTTP请求过程

假设来自客户的请求为:http://localhost:8080/test/index.jsp 请求被发送到本机端口8080

1、用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得。 
2、Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。 
3、Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。 
4、Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有的Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理)。 
5、path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类。 
6、构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost().执行业务逻辑、数据存储等程序。 
7、Context把执行完之后的HttpServletResponse对象返回给Host。 
8、Host把HttpServletResponse对象返回给Engine。 
9、Engine把HttpServletResponse对象返回Connector。 
10、Connector把HttpServletResponse对象返回给客户Browser。

简单模拟Tomcat

  tomcat是通过socket和浏览器获得连接,因为可能有多个请求,所以要用到多线程去接收,通过io流来传递数据。   

package Server;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.StringTokenizer;
public class TomcatServer {
private final static int PORT = 8080;
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(PORT);// 根据端口号启动一个serverSocket
ServletHandler servletHandler = new ServletHandler(server);
servletHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
} private static class ServletHandler extends Thread {
ServerSocket server = null;
public ServletHandler(ServerSocket server) {
this.server = server;
}
@Override
public void run() {
while (true) {
try {
Socket client = null;
client = server.accept();// ServerSocket阻塞等待客户端请求数据
if (client != null) {
try {
System.out.println("接收到一个客户端的请求");
// 根据客户端的Socket对象获取输入流对象。
// 封装字节流到字符流
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
// GET /test.jpg /HTTP1.1
// http请求由三部分组成,分别是:请求行、消息报头、请求正文。
// 这里取的第一行数据就是请求行。http协议详解可以参考http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html说的很详细
String line = reader.readLine();
System.out.println("line: " + line);
// 拆分http请求路径,取http需要请求的资源完整路径
String resource = line.substring(line.indexOf('/'), line.lastIndexOf('/') - 5);
System.out.println("the resource you request is: " + resource);
resource = URLDecoder.decode(resource, "UTF-8");
// 获取到这次请求的方法类型,比如get或post请求
String method = new StringTokenizer(line).nextElement().toString();
System.out.println("the request method you send is: " + method);
// 继续循环读取浏览器客户端发出的一行一行的数据
while ((line = reader.readLine()) != null) {
if (line.equals("")) {// 当line等于空行的时候标志Header消息结束
break;
}
System.out.println("the Http Header is : " + line);
}
// 如果是POST的请求,直接打印POST提交上来的数据
if ("post".equals(method.toLowerCase())) {
System.out.println("the post request body is: " + reader.readLine());
} else if ("get".equals(method.toLowerCase())) {
// 判断是get类型的http请求处理
// 根据http请求的资源后缀名来确定返回数据
// 比如下载一个图片文件,我这里直接给定一个图片路径来模拟下载的情况
if (resource.endsWith(".jpg")) {
transferFileHandle("d://1.jpg", client);
closeSocket(client);
continue;
} else {
// 直接返回一个网页数据
// 其实就是将html的代码以字节流的形式写到IO中反馈给客户端浏览器。
// 浏览器会根据http报文“Content-Type”来知道反馈给浏览器的数据是什么格式的,并进行什么样的处理
PrintStream writer = new PrintStream(client.getOutputStream(), true);
writer.println("HTTP/1.0 200 OK");// 返回应答消息,并结束应答
writer.println("Content-Type:text/html;charset=utf-8");
writer.println();
// writer.println("Content-Length:" +
// html.getBytes().length);// 返回内容字节数
writer.println("<html><body>");
writer.println("<a href='www.baidu.com'>百度</a>");
writer.println(
"<img src='https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png'></img>");
writer.println("</html></body>");
// writer.println("HTTP/1.0 404 Not
// found");// 返回应答消息,并结束应答
writer.println();// 根据 HTTP 协议, 空行将结束头信息
writer.close();
closeSocket(client);// 请求资源处理完毕,关闭socket链接
continue;
}
}
} catch (Exception e) {
System.out.println("HTTP服务器错误:" + e.getLocalizedMessage());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void closeSocket(Socket socket) {
try {
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
System.out.println(socket + "离开了HTTP服务器");
}
private void transferFileHandle(String path, Socket client) {
File fileToSend = new File(path);
if (fileToSend.exists() && !fileToSend.isDirectory()) {
try {
// 根据Socket获取输出流对象,将访问的资源数据写入到输出流中
PrintStream writer = new PrintStream(client.getOutputStream());
writer.println("HTTP/1.0 200 OK");// 返回应答消息,并结束应答
writer.println("Content-Type:application/binary");
writer.println("Content-Length:" + fileToSend.length());// 返回内容字节数
writer.println();// 根据 HTTP 协议, 空行将结束头信息
FileInputStream fis = new FileInputStream(fileToSend);
byte[] buf = new byte[fis.available()];
fis.read(buf);
writer.write(buf);
writer.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

抄录网址

  1. 解析Tomcat内部结构和请求过程
  2. Tomcat运行过程和简单模拟

Tomcat系列(6)——Tomcat处理一个HTTP请求的过程的更多相关文章

  1. 网站开发进阶(四)Tomcat Server处理一个http请求的过程

    Tomcat Server处理一个http请求的过程 假设来自客户的请求为: http://localhost:8080/wsota/wsota_index.jsp 1) 请求被发送到本机端口8080 ...

  2. Tomcat Server处理一个http请求的过程

    Tomcat Server处理一个http请求的过程 假设来自客户的请求为: http://localhost:8080/wsota/wsota_index.jsp 1) 请求被发送到本机端口8080 ...

  3. [转]Tomcat处理一个HTTP请求的过程

    1.Tomcat Server的组成部分 1.1 - Server A Server element represents the entire Catalina servlet container. ...

  4. Tomcat系列(10)——Tomcat主要设计模式5种(外观,责任链,观察者,模板方法,命令模式)

    核心部分 外观模式: RequestFacade应用门面模式(facade)来封装HttpServletRequest. 观察者模式: 事件监听机制,控制组件生命周期的 Lifecycle .Serv ...

  5. Tomcat系列(9)——Tomcat 6方面调优(内存,线程,IO,压缩,缓存,集群)

    核心部分 内存 线程 IO 压缩 缓存 集群 一.JVM内存优化 Tomcat内存优化,包括内存大小,垃圾回收策略. Windows 下的catalina.bat,Linux 下的catalina.s ...

  6. Tomcat系列(8)——Tomcat运行模式连接数和线程池

    Connector的主要功能,是接收连接请求,创建Request和Response对象用于和请求端交换数据:然后分配线程让Engine(也就是Servlet容器)来处理这个请求,并把产生的Reques ...

  7. Tomcat系列(5)——Tomcat配置详细部分

    Tomcat的架构图 Tomcat的组织结构 Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的是Catalina servlet容器,其他组件按照一定的格式要求配置在这个顶层 ...

  8. Tomcat系列(4)——Tomcat 组件及架构详细部分

    核心部分   1. 定义 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta ...

  9. Tomcat系列(3)——Tomcat 组件及架构核心部分 4类主要组件(顶层,连接器,容器,嵌套)

    1.架构图 2. 定义 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta ...

随机推荐

  1. [算法&数据结构]深度优先搜索(Depth First Search)

    深度优先 搜索(DFS, Depth First Search) 从一个顶点v出发,首先将v标记为已遍历的顶点,然后选择一个邻接于v的尚未遍历的顶点u,如果u不存在,本次搜素终止.如果u存在,那么从u ...

  2. 【原】无脑操作:IDEA使用时,提示"8080端口被占用"的解决

    1.问题描述:IDEA使用时,提示"8080端口被占用" Description:    The Tomcat connector configured to listen on ...

  3. 【不定期更新】FPGA/IC岗位常见笔试面试题总结(基础知识)

    1 数字IC(ASIC)设计流程: IC设计分为前端和后端.前端设计主要将HDL语言-->网表,后端设计是网表-->芯片版图. 前端主要有需求分析与架构设计.RTL设计.仿真验证.逻辑综合 ...

  4. JAVA EE获取浏览器和操作系统信息

    一.原理说明:  1. 浏览器访问服务端时,Http请求头上会带上客户端一些信息,可通过"user-agent"获取. //java获取方法如下,其他语言也有自己获取方法 Stri ...

  5. 基于nginx搭建yum源服务器

      1.首先关闭防护墙或者设置规则通过且关闭selinux 停止firewall systemctl stop firewalld 禁止firewall开机启动 systemctl disable f ...

  6. 智表ZCELL产品V1.4.0开发API接口文档 与 产品功能清单

    为了方便大家使用ZCELL,应网友要求,整理编写了相关文档,现与产品一起同步发布,供大家下载使用,使用过程中如有疑问,请与我QQ联系. 智表(ZCELL)V1.4.0版本  功能清单文档下载地址: 功 ...

  7. Jenkins + Ansible + Gitlab之gitlab篇

    前言 持续交付 版本控制器:Gitlab.GitHub 持续集成工具:jenkins 部署工具:ansible  课程安排 Gitlab搭建与流程使用 Ansible环境配置与Playbook编写规范 ...

  8. QTableWidget class

    Help on class QTableWidget in module PyQt5.QtWidgets: class QTableWidget(QTableView)  |  QTableWidge ...

  9. 转载:教你分分钟搞定Docker私有仓库Registry

    一.什么是Docker私有仓库Registry 官方的Docker hub是一个用于管理公共镜像的好地方,我们可以在上面找到我们想要的镜像,也可以把我们自己的镜像推送上去.但是,有时候我们的服务器无法 ...

  10. windows安全更新程序(KB4093112) 安装失败 错误0x80070011

    解决办法:win + R → 输入regedi 将默认安装路径改回C盘的program files