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. Html5 Canvas介绍

    1. 获取绘图上下文 var mycanvas = document.getElementById('mycanvas'); var context = mycanvas.getContext('2d ...

  2. 【spring源码分析】IOC容器初始化(六)

    前言:经过前几篇文章的讲解,我们已经得到了BeanDefinition,接下来将分析Bean的加载. 获取Bean的入口:AbstractApplicationContext#getBean publ ...

  3. Rsync + sersync 实时同步备份

    一      Rsync + Sersync  实时同步介绍 1.Rsync 服务搭建介绍 云机上搭建Rsync server,在本地搭建Rsync Clinet. 2. Sersync 服务搭建介绍 ...

  4. 隐写术之steghide的使用

    steghide不是一个软件,所以下载之后解压缩就可以在命令行中使用. win+R,cmd,回车->进入到steghide.exe所在的文件夹,使用隐藏或者解锁的相应命令,即可隐藏或者解锁. 这 ...

  5. ASP.NET Core 下的依赖注入(一)

    本文介绍利用 Microsoft.Extensions.Configuration.Binder.dll 来实现超级简单的注入. 1. appsettings.json 中定义配置 假设我们有如下配置 ...

  6. EntityFramework 6.x和EntityFramework Core必须需要MultipleActiveResultSets?

    前言 本节我们来探讨到底需不需要在连接字符串上加上MultipleActiveResultSets = true ?,若您有更深层次的理解欢迎留下您的脚印. EntityFramework 6.x和E ...

  7. python中使用redis发布订阅者模型

    redis发布订阅者模型: Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者,订阅者和Channel.发布者和订阅者都是Redis客户端,Channel则 ...

  8. [Alpha阶段]事后分析博客

    目录 Alpha阶段事后分析博客 设想和目标 计划 资源 变更管理 设计/实现 测试/发布 团队的角色,管理,合作 总结 讨论照片 Alpha阶段事后分析博客 作业要求:Alpha阶段事后分析 设想和 ...

  9. Python----多元线性回归

    多元线性回归 1.多元线性回归方程和简单线性回归方程类似,不同的是由于因变量个数的增加,求取参数的个数也相应增加,推导和求取过程也不一样.. y=β0+β1x1+β2x2+ ... +βpxp+ε 对 ...

  10. LinkedHashMap源码分析

    hashMap源码分析:hashMap源码分析 版本说明:jdk1.7LinkedHashMap继承于HashMap,是一个有序的Map接口的实现.有序指的是元素可以按照一定的顺序排列,比如元素的插入 ...