《HowTomcatWork》笔记总结(一)(下)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 《HowTomcatWork》笔记总结(一)(下)

基本步骤:


下面是代码的基本交互步骤:

  1. 创建httpserver 对象
  2. 绑定端口和主机,建立套接字连接
  3. accept()方法等待请求,阻塞当前线程
  4. 创建reuqest 请求对象
  5. 获取inputstream 解析请求信息
  6. 获取请求到uri,设置到Request对象
  7. 创建 response 响应对象
  8. 设置响应对象的request,拿到uri, 同时使用Io,读取请求对应到文件
  9. outputstream 解析文件流数据,使用write 返回到客户端
  10. 无论成功还是失败,关闭流(重要)


补充内容:



这里重点关注关于套接字的一些知识


ServerSocket


服务器套接字的另一个重要的属性是 backlog,这是服务器套接字开始==拒绝==传入的请求之前,传入的连接请求的==最大队列长度==。


parseUri() 处理逻辑


GET /index.html HTTP/1.1。parse 方法从传递给 Requst 对象的套接字的 InputStream 中读取整个字节流并在一个缓冲区中存储字节数组。然后它使用缓冲区字节数据的字节来填入一个 StringBuffer 对象,并且把代表 StringBuffer 的字符串传递给 parseUri 方法。


Http请求对于servlet的操作


当第一次调用 servlet 的时候,加载该 servlet 类并调用 servlet 的 init 方法(仅仅一次)。

  • 对每次请求,构造一个 javax.servlet.ServletRequest 实例和一个 javax.servlet.ServletResponse 实例。
  • 调用 servlet 的 service 方法,同时传递 ServletRequest 和 ServletResponse 对象。
  • 当 servlet 类被关闭的时候,调用 servlet 的 destroy 方法并卸载 servlet 类。

本章的第一个servlet容器不是全功能的。因此,她不能运行什么除了非常简单的servlet, 而且也不调用 servlet 的 init 方法和 destroy 方法。相反它做了下面的事情:

  • 等待 HTTP 请求。
  • 构造一个 ServletRequest 对象和一个 ServletResponse 对象。
  • 假如该请求需要一个静态资源的话,调用 StaticResourceProcessor 实例的 process 方

法,同时传递 ServletRequest 和 ServletResponse 对象。

  • 假如该请求需要一个 servlet 的话,加载 servlet 类并调用 servlet 的 service 方法,

同时传递 ServletRequest 和 ServletResponse 对象


StringManager


特点:


  1. 使用单例模式
  2. 每个实例会读取包对应的一个属性文件
  3. StringManager 类被设计成一个 StringManager实例可以被包里边的所有类共享
  4. getManager() 方法被 同步修饰,并且使用hashtable对于manager进行管理(tomcat4)


核心方法解释


SocketInputStream:套接字读取流,主要用于处理Http请求中的各种参数,为了提高效率,使用懒加载特性读取

  1. 回收检查流数据
  2. 检查空行,如果出现-1抛出结尾异常
  3. 获取servlet方法名称
  1. 如果缓冲区已经满了,则进行扩展
  1. 我们在内部缓冲区的尽头
  2. 如果到了缓冲区结尾,将指针归位
  1. 这里有一个关键点:System.arraycopy 用来扩展缓冲区
  1. 阅读协议


模块解释


关于部分模块的相关解释。


解析头部


  • 你可以通过使用类的无参数构造方法构造一个 HttpHeader 实例。
  • 一旦你拥有一个HttpHeader实例,你可以把它传递给SocketInputStream的readHeader

方法。假如这里有头部需要读取,readHeader 方法将会相应的填充 HttpHeader 对象。 假如再也没有头部需要读取了,HttpHeader实例的nameEnd和valueEnd字段将会置零。

  • 为了获取头部的名称和值,使用下面的方法:
  • String name = new String(header.name, 0, header.nameEnd);
  • String value = new String(header.value, 0, header.valueEnd);


启动器


  • 启动应用程序
  • 连接器
  • 创建一个 HttpRequest 对象
  • 创建一个 HttpResponse 对象
  • 静态资源处理器和 servlet 处理器
  • 运行应用程序

startup 模块只有一个类,Bootstrap,用来启动应用的。connector 模块的类可以分为五组:


  • 连接器和它的支撑类(HttpConnector 和 HttpProcessor)。
  • 指代 HTTP 请求的类(HttpRequest)和它的辅助类。
  • 指代 HTTP 响应的类(HttpResponse)和它的辅助类。
  • Facade 类(HttpRequestFacade 和 HttpResponseFacade)。
  • Constant 类


问题以及解决


如何避免在servlet调用连接器的时候,不需要请求参数可以避免掉getParamMap,getAttribute等昂贵开销的操作?

Tomcat 的默认连接器(和本章应用程序的连接器)试图不解析参数直到 servlet 真正需要它的时候,通过这样来获得更高效率


小知识补充


  1. System 在打印的时候 print 方法不会刷新输出。
  2. 在一个 servlet 容器里边,一个类加载器可以找到 servlet 的地方被称为资源库(repository)。
  3. 通过外观模式将Request对象的细节隐藏,setvlet调用内部无法知道,但是在解析的时候依然可以相互通信,只需要使用faced将接口进行一层包裹, 即可保证getUri()方法安全性


总结


书中第一个章节内容比较简单,后续章节代码的难度会逐渐上升,同时使用了不少的设计模式也是需要多加阅读理解和消化的


写在最后


这篇笔记目的是让更多人了解这本书,这本书算是一本神书,毕竟开发的原作者自己写的东西毫无疑问是一手知识了。

相关文章
|
JavaScript 前端开发 算法
前端面试题(五.3)(20道)上
前端面试题(五.3)(20道)
92 0
|
Java 机器人 数据安全/隐私保护
蓝桥杯历届真题题目+解析+代码+答案(2013-2020)(JavaA、B、C组)(C++语言)(Python)
蓝桥杯历届真题题目+解析+代码+答案(2013-2020)(JavaA、B、C组)(C++语言)(Python)
304 0
|
12月前
|
机器学习/深度学习 算法 Java
算法宝典2——Java版本(此系列持续更新,这篇文章目前3道)(有题目的跳转链接)(此份宝典包含了二叉树的算法题)
算法宝典2——Java版本(此系列持续更新,这篇文章目前3道)(有题目的跳转链接)(此份宝典包含了二叉树的算法题)
|
12月前
|
存储 算法 Java
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)(下)
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)(下)
|
编译器 C语言 C++
C++入门(一)(上)
C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度 的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
96 0
C++入门(一)(上)
|
存储 安全 编译器
|
网络协议 安全 算法
大网进阶安全刷题讲解(带答案)(1)(上)
大网进阶安全刷题讲解(带答案)(1)
82 0
|
网络协议 安全 算法
大网进阶安全刷题讲解(带答案)(1)(下)
大网进阶安全刷题讲解(带答案)(1)
97 0
|
自然语言处理 编译器 Linux
C++入门(一)(下)
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该 形参的缺省值,否则使用指定的实参。
81 0
|
C++
C++学习——坚持(二)(2)
C++学习——坚持(二)(2)
149 0
C++学习——坚持(二)(2)
下一篇
无影云桌面