整体架构图

一. 启动阶段

BootStrap的main方法加载server.xml配置文件,封装成Server,Service,Connector,Engine等java对象

Server初始化==>Service初始化==>Connector初始化==>Engine初始化==>Host初始化==>Context初始化 WAR解压 创建Servlet

Connector初始化:绑定端口,创建BIO NIO NIO2线程池

Connector.setProtocol是在解析server.xml配置文件时绑定关系

启动Connector initInternal() ===>ProtocolHandler.init() ==> Endpoint.init()-->Endpoint.bind()

Connector作用(接收请求时):

ServerSocket(Channel)接收socket请求创建Socket, 并将Socket.InputStream中的内容封装成javax.servlet.http.HttpServletRequest的实现类, 经过多个valve filter之后传递到Container的Servlet(SpringMVC)中, servlet.doService完成之后由HttpServletResponse(持有请求时创建的socket?).outputStream回写内容到socket中

Protocol 配置在server.xml的<connector >标签的属性中, 作用:根据配置创建不同的Endpoint

tomcat8.5

Endpoint 具体协议的实现, 完成绑定端口及创建线程池

tomcat8.5

tomcat8.0 

tomcat 7.0

Endpoint.startInternal()

7.0默认使用JIOEndpoint, 8.0以上默认使用NIOEndpoint

//搞懂NIO NIO2===>

二、接收浏览器HTTP请求

整体流程:

NIOEndpoint ---> Http11Processor(创建Request, Response) ---> CoyoteAdapter --> Container -->

PipeLine(StandardEngineValve, StandardHostValve, StandardContextValve, StandardWrapperValve)--> Servlet.doService

2.1 Endpoint中request创建

JIOEndpoint在接收socket请求后,直接将Request交给了worker线程

NIOEndpoint.Acceptor在接收到请求后(while循环一直监听),将PollerEvent事件注册到NIOEndpoint.Poller(持有selector对象)的事件队列中,并调用selector.waitup() 只调用一次,

private void addEvent(PollerEvent event) {events.offer(event);if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();
}

Poller的while循环中查找到PollerEvent, 调用processKey()方法-->AbstractEndpoint#processSocket()在这里创建SocketProcessor(Runable)并提交给Executor线程池处理。

SocketProcessor --> Http11Processor.service() readsocket&buildRequest-->CoyoteAdatper.service()

2.2 CoyoteAdapter中处理Request

Servlet3.1 异步Request, 在Servlet里面设置.isAsync, coyoteAdapter invoke服务方法后直接返回,socket并没有释放

org.apache.catalina.connector.CoyoteAdapter#service

 1             if (postParseSuccess) {
 2                 //check valves if we support async
 3                 request.setAsyncSupported(
 4                         connector.getService().getContainer().getPipeline().isAsyncSupported());
 5                 // Calling the container  调用filter servlet
 6                 connector.getService().getContainer().getPipeline().getFirst().invoke(
 7                         request, response);
 8             }
 9             if (request.isAsync()) {
10                 async = true;
11                 ReadListener readListener = req.getReadListener();
12                 if (readListener != null && request.isFinished()) {
13                     // Possible the all data may have been read during service()
14                     // method so this needs to be checked here
15                     ClassLoader oldCL = null;
16                     try {
17                         oldCL = request.getContext().bind(false, null);
18                         if (req.sendAllDataReadEvent()) {
19                             req.getReadListener().onAllDataRead();
20                         }
21                     } finally {
22                         request.getContext().unbind(false, oldCL);
23                     }
24                 }
25
26                 Throwable throwable =
27                         (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
28
29                 // If an async request was started, is not going to end once
30                 // this container thread finishes and an error occurred, trigger
31                 // the async error process
32                 if (!request.isAsyncCompleting() && throwable != null) {
33                     request.getAsyncContextInternal().setErrorState(throwable, true);
34                 }
35             } else {
36                 request.finishRequest(); // 非异步的请求处理之后, 会释放socket
37                 response.finishResponse();
38             }

session创建时机, 在Request.getSession时根据请求中的JSESSIONID查找,如果id为null,首次创建,新的请求中就携带了JSESSIONID

Connector创建的是org.apache.catalina.connector.Request

org.apache.catalina.core.StandardWrapperValve --> 具体某个Servlet (DispatchServlet),  初始化FilterChain, 然后调用各个filter, 最后到Servlet.doService

filterChain.doFilter    (request.getRequest(), response.getResponse());

压缩版的两个默认Servlet: DefaultServlet处理静态资源,JSPServlet创建HttpServletRequest,对connector.Request又包一层

2.3 Response的socket WRITE,CLOSE事件在NIOEndpoint中的处理

和socket OPEN_READ事件基本一致

其他参考:

Http中socket长连接短连接使用场景 http://www.cnblogs.com/0201zcr/p/4694945.html

程序中设置为长连接 1. socket.setKeepAlive(true)   2.socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);

See:

http://tomcat.apache.org/tomcat-8.0-doc/architecture/requestProcess.html

http://tomcat.apache.org/tomcat-8.0-doc/config/http.html#NIO2_specific_configuration

转载于:https://www.cnblogs.com/yszzu/p/9261117.html

Tomcat从socket到java Servlet相关推荐

  1. java servlet dao_Java+MyEclipse+Tomcat 详解Servlet和DAO数据库增删改查操作(源码)

    [实例简介] 该资源主要参考自己的博客http://blog.csdn.net/eastmount/article/details/45936121 讲诉Java+MyEclipse+Tomcat 详 ...

  2. Java+Servlet+JSP+Mysql+Tomcat实现Web学生选课管理系统

    Java实现Web学生选课管理系统 一.系统介绍 1.软件环境 2.系统功能 3.数据库 二.系统展示 1.登录页面 2.学生-主页面 3.学生-查看个人信息 4.学生-选择课程 5.学生-查看已选课 ...

  3. Java Servlet和JSP教程

    http://www.bccn.net/article/web/jsp/jc/200409/72.html 简介 这是一个比较完整的Servlet.JSP教程,包含大量的实用资料和示例,仙人掌工作室倾 ...

  4. Java Servlet的前100个问题

    1)是" servlets"目录还是" servlet"目录? 回答: 对于Java Web Server: 在文件系统上,它是" servlet&q ...

  5. java servlet 多线程_Servlet的多线程和线程安全

    线程安全 首先说明一下对线程安全的讨论,哪种情况我们可以称作线程安全? 网上对线程安全有很多描述,我比较喜欢<Java并发编程实战>给出的定义,"当多个线程访问某个类时,不管运行 ...

  6. jsp java 登陆_jsp+java servlet实现简单用户登录

    jsp+java servlet实现简单用户登录(使用数据库,包括注册页面) 功能介绍 本项目通过使用jsp和servlet实现简单的用户登录.主要逻辑为:如果用户不存在,则首先进行注册(注册信息同步 ...

  7. Java Servlet完全教程

    本文来自Java Servlet完全教程 Servlet 是一些遵从Java Servlet API的Java类,这些Java类可以响应请求.尽管Servlet可以响应任意类型的请求,但是它们使用最广 ...

  8. Java Servlet工作原理问答

    导读 本文来自stackoverflow的问答,讨论了Java Servlet的工作机制,如何进行实例化.共享变量和多线程处理. 问题:Servlet是如何工作的?Servlet 如何实例化.共享变量 ...

  9. [转]Java——Servlet的配置和测试

    本文转自:http://blog.csdn.net/makefish/article/details/6904807 本文以一个实例介绍如何用Java开发Servlet. 主要内容有: 配置和验证To ...

最新文章

  1. Python 运算符重载
  2. idea创建javaweb项目连接mysql【HTTP Status 500】
  3. C++实现神经网络之一 | Net类的设计和神经网络的初始化
  4. iOS开发之单元测试
  5. python语法学习第九天--else和with语句
  6. 面向对象编程(十)——继承之Super关键字及内存分析
  7. shell 截取文件名及扩展名
  8. Linux命令——创建删除文件
  9. 基于Jsp的简单论坛(BBS)的设计与实现(附代码)
  10. 如何建语料库_语料库-如何建设语料?如何建设语料库 爱问知识人
  11. 基于FPGA的可控倒计时计数器
  12. windows 7 官方旗舰版
  13. Arduino +合宙ESP32C3 +1.8/1.44 寸TFT液晶屏驱动显示
  14. 华为手机解析出现问题
  15. vba中find方法查找
  16. 庞加莱买面包的故事(二)
  17. Flipped (怦然心动)
  18. 输出三位数的个十百位数
  19. Android 开源交流 QQ 群分享汇总
  20. 用java输出出生日期,生成随机出生日期

热门文章

  1. 【动态规划】计蒜客:跳木桩(最长递增子序列的变体)
  2. 最简单的基于FFmpeg的移动端例子附件:SDL Android HelloWorld
  3. Java 获取系统信息
  4. mysql大表数据抽取_从云数据迁移服务看MySQL大表抽取模式
  5. mysql句式增删改,MySQL 增删改语句
  6. 猜数游戏控制猜测次数c语言,C语言小游戏之猜数字,三子棋游戏
  7. linux 挂起后无法唤醒屏幕
  8. Springboot项目启动时加载数据库数据到内存
  9. 纯html网页,如何快速把所有字体的颜色都改成黑色的,原来模板默认的字体是灰色
  10. UVa12545 - Bits Equalizer