- 浏览: 133621 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
housheng33:
你好,请教 JEECMS oralce问题
qq3319326 ...
JEECMS -
hanhongqiangwml:
public void contextDestroyed(S ...
ServletContextListener 使用 -
hanhongqiangwml:
...
ServletContextListener 使用 -
hanhongqiangwml:
tfgfghfghfgh
ServletContextListener 使用 -
赤道螞蟻:
太實用了 ,謝謝!
StringUtil 用法
Connector是Tomcat最核心的组件之一,负责处理一个WebServer最核心的连接管理、Net IO、线程(可选)、协议解析和处理的工作。
一、连接器介绍
在开始Connector探索之路之前,先看看Connector几个关键字
- NIO:Tomcat可以利用Java比较新的NIO技术,提升高并发下的Socket性能
- AJP:Apache JServ Protocol,AJP的提出当然还是为了解决java亘古不变的问题——性能,AJP协议是基于包的长连接协议,以减少前端Proxy与Tomcat连接Socket连接创建的代价,目前Apache通过JK和AJP_ROXY的方式支持AJP协议,需要注意的是,虽然Nginx作为代理服务器性能强劲,但其只能通过HTTP PROXY的方式与后端的Tomcat联系,因此如果从作为代理服务器的角度上讲,在这种情况下Nginx未必会比Apache体现出更优的性能
- APR/Native:Apache Portable Runtime,还是一个词,性能。APR的提出利用Native代码更好地解决性能问题,更好地与本地服务器(linux)打交道。让我们看看Tomcat文档对APR的介绍
These features allows making Tomcat a general purpose webserver, will enable much better integration with other native web technologies, and overall make Java much more viable as a full fledged webserver platform rather than simply a backend focused technology.
通过对如上名词的组合,Tomcat组成了如下的Connector系列:
- Http11Protocol:支持HTTP1.1协议的连接器
- Http11NioProtocol:支持HTTP1.1 协议+ NIO的连接器
- Http11AprProtocol:使用APR技术处理连接的连接器
- AjpProtocol:支持AJP协议的连接器
- AjpAprProtocol:使用APR技术处理连接的连接器
二、范例
我们以最简单的Http11Protocol为例,看看从请求进来到处理完毕,连接器部件是处理处理的。首先我们利用Tomcat组件组成我们一个最简单的WebServer,其具备如下功能:
- 监停某个端口,接受客户端的请求,并将请求分配给处理线程
- 处理线程处理请求,分析HTTP1.1请求,封装Request/Response对象,并将请求由请求处理器处理
- 实现最简单的请求处理器,向客户端打印Hello World
代码非常简单,首先是主功能(这里,我们利用JDK5.0的线程池,连接器不再管理线程功能):
- package ray.tomcat.test;
- import java.util.concurrent.BlockingQueue;
- import java.util.concurrent.LinkedBlockingQueue;
- import java.util.concurrent.ThreadPoolExecutor;
- import java.util.concurrent.TimeUnit;
- import org.apache.coyote.http11.Http11Protocol;
- public class TomcatMainV2
- {
- public static void main(String[] args) throws Exception
- {
- Http11Protocol protocol = new Http11Protocol();
- protocol.setPort(8000);
- ThreadPoolExecutor threadPoolExecutor = createThreadPoolExecutor();
- threadPoolExecutor.prestartCoreThread();
- protocol.setExecutor(threadPoolExecutor);
- protocol.setAdapter(new MyHandler());
- protocol.init();
- protocol.start();
- }
- public static ThreadPoolExecutor createThreadPoolExecutor()
- {
- int corePoolSize = 2;
- int maximumPoolSize = 10;
- long keepAliveTime = 60;
- TimeUnit unit = TimeUnit.SECONDS;
- BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
- ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
- corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
- return threadPoolExecutor;
- }
- }
package ray.tomcat.test; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.coyote.http11.Http11Protocol; public class TomcatMainV2 { public static void main(String[] args) throws Exception { Http11Protocol protocol = new Http11Protocol(); protocol.setPort(8000); ThreadPoolExecutor threadPoolExecutor = createThreadPoolExecutor(); threadPoolExecutor.prestartCoreThread(); protocol.setExecutor(threadPoolExecutor); protocol.setAdapter(new MyHandler()); protocol.init(); protocol.start(); } public static ThreadPoolExecutor createThreadPoolExecutor() { int corePoolSize = 2; int maximumPoolSize = 10; long keepAliveTime = 60; TimeUnit unit = TimeUnit.SECONDS; BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); return threadPoolExecutor; } }
请求处理器向客户端打引Hello World,代码如下
- package ray.tomcat.test;
- import java.io.ByteArrayOutputStream;
- import java.io.OutputStreamWriter;
- import java.io.PrintWriter;
- import org.apache.coyote.Adapter;
- import org.apache.coyote.Request;
- import org.apache.coyote.Response;
- import org.apache.tomcat.util.buf.ByteChunk;
- import org.apache.tomcat.util.net.SocketStatus;
- public class MyHandler implements Adapter
- {
- //支持Comet,Servlet3.0将对Comet提供支持,Tomcat6目前是非标准的实现
- public boolean event(Request req, Response res, SocketStatus status)
- throws Exception
- {
- System.out.println("event");
- return false;
- }
- //请求处理
- public void service(Request req, Response res) throws Exception
- {
- System.out.println("service");
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos));
- writer.println("Hello World");
- writer.flush();
- ByteChunk byteChunk = new ByteChunk();
- byteChunk.append(baos.toByteArray(), 0, baos.size());
- res.doWrite(byteChunk);
- }
- }
package ray.tomcat.test; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import org.apache.coyote.Adapter; import org.apache.coyote.Request; import org.apache.coyote.Response; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.net.SocketStatus; public class MyHandler implements Adapter { //支持Comet,Servlet3.0将对Comet提供支持,Tomcat6目前是非标准的实现 public boolean event(Request req, Response res, SocketStatus status) throws Exception { System.out.println("event"); return false; } //请求处理 public void service(Request req, Response res) throws Exception { System.out.println("service"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(baos)); writer.println("Hello World"); writer.flush(); ByteChunk byteChunk = new ByteChunk(); byteChunk.append(baos.toByteArray(), 0, baos.size()); res.doWrite(byteChunk); } }
运行主程序,在浏览器中输入http://127.0.0.1:8000,我们可以看到打印”Hello World”
三、分析
以如上Http11Protocol为例,我们可以看到,Tomcat实现一个最简单的处理Web请求的代码其实非常简单,其主要包括如下核心处理类:
- Http11Protocol:Http1.1协议处理入口类,其本身没有太多逻辑,对请求主要由JIoEndPoint类处理
- Http11Protocol$Http11ConnectionHandler:连接管理器,管理连接处理队列,并分配Http11Processor对请求进行处理
- Http11Processor:请求处理器,负责HTTP1.0协议相关的工作,包括解析请求和处理响应信息,并调用Adapter做实际的处理工作,如上我们看到了我们自定义的Adapter实现响应”Hello World”
- JIoEndPoint:监停端口,启动接受线程准备接收请求,在请求接受后转给工作线程处理
- JIoEndPoint$Acceptor:请求接收器,接收后将Socket分配给工作线程继续后续处理
- JIoEndPoint$Worker:工作线程,使用Handler来处理请求,对于我们的HTTP1.1协议来说,其实现是Http11Protocol$Http11ConnectionHandler。这部分不是必须的,也可以选择JDK的concurrent包的线程池
实际上各种连接器实现基本大同小异,基本上都是由如上部分组合而成
1.初始化:首先,还是从入口开始,先看看初始化init
- public void init() throws Exception {
- endpoint.setName(getName());
- endpoint.setHandler(cHandler); //请求处理器,对于HTTP1.1协议,是Http11Protocol$Http11ConnectionHandler
- // 初始化ServerSocket工厂类,如果需SSL/TLS支持,使用JSSESocketFactory/PureTLSSocketFactory
- . . . (略)
- //主要的初始化过程实际是在endpoint(JIoEndpoint)
- endpoint.init();
- . . . (略)
- }
public void init() throws Exception { endpoint.setName(getName()); endpoint.setHandler(cHandler); //请求处理器,对于HTTP1.1协议,是Http11Protocol$Http11ConnectionHandler // 初始化ServerSocket工厂类,如果需SSL/TLS支持,使用JSSESocketFactory/PureTLSSocketFactory . . . (略) //主要的初始化过程实际是在endpoint(JIoEndpoint) endpoint.init(); . . . (略) }
Http11Protocol的初始化非常简单,准备好ServerSocket工厂,调用JIoEndPoint的初始化。让我们接下来看看JIoEndPoint的初始化过程
- public void init()
- throws Exception {
- if (initialized)
- return;
- // Initialize thread count defaults for acceptor
- // 请求接收处理线程,这个值实际1已经足够
- if (acceptorThreadCount == 0) {
- acceptorThreadCount = 1;
- }
- if (serverSocketFactory == null) {
- serverSocketFactory = ServerSocketFactory.getDefault();
- }
- //创建监停ServerSocket,port为监听端口,address为监停地址
- // backlog为连接请求队列容量(@param backlog how many connections are queued)
- if (serverSocket == null) {
- try {
- if (address == null) {
- serverSocket = serverSocketFactory.createSocket(port, backlog);
- } else {
- serverSocket = serverSocketFactory.createSocket(port, backlog, address);
- }
- } catch (BindException be) {
- throw new BindException(be.getMessage() + ":" + port);
- }
- }
- //if( serverTimeout >= 0 )
- // serverSocket.setSoTimeout( serverTimeout );
- initialized = true;
- }
public void init() throws Exception { if (initialized) return; // Initialize thread count defaults for acceptor // 请求接收处理线程,这个值实际1已经足够 if (acceptorThreadCount == 0) { acceptorThreadCount = 1; } if (serverSocketFactory == null) { serverSocketFactory = ServerSocketFactory.getDefault(); } //创建监停ServerSocket,port为监听端口,address为监停地址 // backlog为连接请求队列容量(@param backlog how many connections are queued) if (serverSocket == null) { try { if (address == null) { serverSocket = serverSocketFactory.createSocket(port, backlog); } else { serverSocket = serverSocketFactory.createSocket(port, backlog, address); } } catch (BindException be) { throw new BindException(be.getMessage() + ":" + port); } } //if( serverTimeout >= 0 ) // serverSocket.setSoTimeout( serverTimeout ); initialized = true; }
可以看到,监停端口在此处准备就绪
- public void start()
- throws Exception {
- // Initialize socket if not done before
- if (!initialized) {
- init();
- }
- if (!running) {
- running = true;
- paused = false;
- // Create worker collection
- // 初始化工作线程池,有WorkerStack(Tomcat自实现)和Executor(JDK concurrent包)两种实现
- if (executor == null) {
- workers = new WorkerStack(maxThreads);
- }
- // Start acceptor threads
- // 启动请求连接接收处理线程
- for (int i = 0; i < acceptorThreadCount; i++) {
- Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
- acceptorThread.setPriority(threadPriority);
- acceptorThread.setDaemon(daemon); //设置是否daemon参数,默认为true
- acceptorThread.start();
- }
- }
- }
public void start() throws Exception { // Initialize socket if not done before if (!initialized) { init(); } if (!running) { running = true; paused = false; // Create worker collection // 初始化工作线程池,有WorkerStack(Tomcat自实现)和Executor(JDK concurrent包)两种实现 if (executor == null) { workers = new WorkerStack(maxThreads); } // Start acceptor threads // 启动请求连接接收处理线程 for (int i = 0; i < acceptorThreadCount; i++) { Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i); acceptorThread.setPriority(threadPriority); acceptorThread.setDaemon(daemon); //设置是否daemon参数,默认为true acceptorThread.start(); } } }
2.准备好连接处理:初始化完毕,准备好连接处理,准备接收连接上来,同样的,Http11Protocol的start基本没干啥事,调用一下JIoEndPoint的start,我们来看看JIoEndPoint的start
- public void start()
- throws Exception {
- // Initialize socket if not done before
- if (!initialized) {
- init();
- }
- if (!running) {
- running = true;
- paused = false;
- // Create worker collection
- // 初始化工作线程池,有WorkerStack(Tomcat自实现)和Executor(JDK concurrent包)两种实现
- if (executor == null) {
- workers = new WorkerStack(maxThreads);
- }
- // Start acceptor threads
- // 启动请求连接接收处理线程
- for (int i = 0; i < acceptorThreadCount; i++) {
- Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
- acceptorThread.setPriority(threadPriority);
- acceptorThread.setDaemon(daemon); //设置是否daemon参数,默认为true
- acceptorThread.start();
- }
- }
- }
public void start() throws Exception { // Initialize socket if not done before if (!initialized) { init(); } if (!running) { running = true; paused = false; // Create worker collection // 初始化工作线程池,有WorkerStack(Tomcat自实现)和Executor(JDK concurrent包)两种实现 if (executor == null) { workers = new WorkerStack(maxThreads); } // Start acceptor threads // 启动请求连接接收处理线程 for (int i = 0; i < acceptorThreadCount; i++) { Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i); acceptorThread.setPriority(threadPriority); acceptorThread.setDaemon(daemon); //设置是否daemon参数,默认为true acceptorThread.start(); } } }
主要处理的事情无非就是准备和工作线程(处理具体请求的线程度池,可选,也可以使用JDK5.0的线程池),连接请求接收处理线程(代码中,一般acceptorThreadCount=1)
3.连接请求接收处理:准备就绪,可以连接入请求了。现在工作已经转到了Acceptor(JIoEndPoint$Acceptor)这里,我们看看Acceptor到底做了些啥
- public void run() {
- // Loop until we receive a shutdown command
- while (running) {
- . . . (略)
- //阻塞等待客户端连接
- Socket socket = serverSocketFactory.acceptSocket(serverSocket);
- serverSocketFactory.initSocket(socket);
- // Hand this socket off to an appropriate processor
- if (!processSocket(socket)) {
- // Close socket right away
- try {
- socket.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- . . . (略)
- }
- }
- . . . (略)
- protected boolean processSocket(Socket socket) {
- try {
- //由工作线程继续后续的处理
- if (executor == null) {
- getWorkerThread().assign(socket);
- } else {
- executor.execute(new SocketProcessor(socket));
- }
- } catch (Throwable t) {
- . . . (略)
- return false;
- }
- return true;
- }
public void run() { // Loop until we receive a shutdown command while (running) { . . . (略) //阻塞等待客户端连接 Socket socket = serverSocketFactory.acceptSocket(serverSocket); serverSocketFactory.initSocket(socket); // Hand this socket off to an appropriate processor if (!processSocket(socket)) { // Close socket right away try { socket.close(); } catch (IOException e) { // Ignore } } . . . (略) } } . . . (略) protected boolean processSocket(Socket socket) { try { //由工作线程继续后续的处理 if (executor == null) { getWorkerThread().assign(socket); } else { executor.execute(new SocketProcessor(socket)); } } catch (Throwable t) { . . . (略) return false; } return true; }
实际上也没有什么复杂的工作,无非就是有连接上来之后,将连接转交给工作线程(SocketProcessor)去处理
4.工作线程:SocketProcessor
- public void run() {
- // Process the request from this socket
- if (!setSocketOptions(socket) || !handler.process(socket)) {
- // Close socket
- try {
- socket.close();
- } catch (IOException e) {
- }
- }
- // Finish up this request
- socket = null;
- }
public void run() { // Process the request from this socket if (!setSocketOptions(socket) || !handler.process(socket)) { // Close socket try { socket.close(); } catch (IOException e) { } } // Finish up this request socket = null; }
工作线程主要是设置一下Socket参数,然后将请求转交给handler去处理,需要注意一下如下几个连接参数的意义:
- SO_LINGER:若设置了SO_LINGER并确定了非零的超时间隔,则closesocket()调用阻塞进程,直到所剩数据发送完毕或超时。这种关闭称为“优雅的”关 闭。请注意如果套接口置为非阻塞且SO_LINGER设为非零超时,则closesocket()调用将以WSAEWOULDBLOCK错误返回。若在一个流类套接口上设置了SO_DONTLINGER,则closesocket()调用立即返回。但是,如果可能,排队的数据将在套接口关闭前发送。请注意,在这种情况下WINDOWS套接口实现将在 一段不确定的时间内保留套接口以及其他资源(TIME_WAIT),这对于想用所以套接口的应用程序来说有一定影响。默认此参数不打开
- TCP_NODELAY:是否打开Nagle,默认打开,使用Nagle算法是为了避免多次发送小的分组,而是累计到一定程度或者超过一定时间后才一起发送。对于AJP连接,可能需要关注一下这个选项。
- SO_TIMEOUT:JDK API注释如下,With this option set to a non-zero timeout,a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0。默认设置的是60秒
关于默认的设置,可以参见org.apache.coyote.http11.Constants定义
5.最终请求终于回到了Handler,此处的Handler实现是org.apache.coyote.http11.Http11Processor,其主要处理一些HTTP协议性细节的东西,此处代码不再列出,有兴趣可以自行读代码。最终请求终于回到了我们的Adapter对象,一个请求处理完毕,功德圆满。
发表评论
-
java正则表达式测试工具
2017-04-13 11:45 480import javax.swing.*; impor ... -
java中volatile关键字
2017-04-13 11:17 354java中volatile关键字的含 ... -
环境搭建网址汇总
2016-06-17 16:38 442文章出处:http://blog.csdn.net/u0131 ... -
一个很不错开源资源网站
2016-06-17 16:32 587一个很不错的开源资源网站,在此做个记录,有兴趣的朋友也可以去看 ... -
JAVA开源加密包使用
2016-04-05 15:34 431<div class="iteye-blog- ... -
H2数据库
2011-11-28 15:12 1178http://www.h2database.com/html/ ... -
JAVA操作EXCEL实现搜集
2011-09-18 18:17 779http://blog.csdn.net/liuyang116 ... -
Eclipse启动报错
2011-02-28 21:42 1032Errors: JVM terminated.Exit C ... -
Excel下载时避免迅雷下载
2011-02-11 19:01 1829在利用开源MyXls导出Excel时,对于安装着迅雷的客户端, ... -
java国际化支持
2011-01-16 19:52 1054java国际化,2个主要类:java.util.Locale ... -
C3P0POOL连接池
2010-09-30 14:53 971package com.sanxia.utils;import ... -
JCP 简介
2010-05-19 10:36 1501Java 技术是最初由 Sun Microsystems 公 ... -
serialVersionUID 的介绍
2010-05-18 14:56 867设置 serialVersionUID默认的生成方式: pr ... -
kaptcha 验证码组件使用简介
2010-05-18 14:26 2562使用方法: 1、到http://code.google.co ... -
在程序中设置hibernate configuration的Property
2010-05-18 10:41 1039在程序中设置hibernate configuration的P ... -
tomcat内存设置方法
2010-03-17 15:13 3242Tomcat内存设置方法 windows中大家都知道,JAV ... -
java timer 使用简单例子
2009-09-10 11:50 4614有时想要换一定的间隔时间执行重复的任务,java.util.T ... -
使用Java中的Timer和TimerTask
2009-09-10 11:44 1297有的时候我们需要每隔一段时间去执行某个任务,在Java中提供了 ... -
StringUtil 用法
2009-08-21 15:36 2060org.apache.commons.lang.Strin ... -
dozer 使用
2009-07-31 17:41 1401加载dozer组件工具: List mappingfil ...
相关推荐
Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...
Tomcat源码剖析,顾名思义是对Tomcat源代码的深入分析和解释。Tomcat是一个开源的Servlet容器,主要用于Java程序,它可以运行在不同的操作系统上。本知识点的剖析将从以下几个方面进行展开。 首先,Tomcat的源码...
总之,《Tomcat深入剖析》结合源码分析,是一本全面且深入的Tomcat学习资源,无论是初学者还是经验丰富的开发者,都能从中受益匪浅。通过学习,读者不仅能够掌握Tomcat的基本操作,还能深入了解其内部机制,为构建...
【标题】"Tomcat源码分析" 在深入探讨Tomcat源码之前,首先需要了解Tomcat是什么。Tomcat是一款开源的、基于Java的Web应用服务器,由Apache软件基金会开发。它实现了Java Servlet和JavaServer Pages(JSP)规范,...
源码解析部分则是对Tomcat源码的深度剖析,涵盖了关键类和方法的作用、设计模式的运用以及性能优化技巧。这有助于开发者理解Tomcat内部的工作流程,例如,如何处理HTTP请求的生命周期,以及线程池是如何调度和管理的...
《深入理解Tomcat:工作原理与源码剖析》 Tomcat作为一款开源的Java Servlet容器,是Apache软件基金会Jakarta项目的重要组成部分,广泛应用于各种Java Web应用的部署。本篇文章将深入探讨Tomcat的工作原理,并结合...
Tomcat核心源码剖析.rar
《深入剖析Tomcat源码》是一本专门为Java开发者和系统管理员设计的专业书籍,它旨在帮助读者深入了解Apache Tomcat服务器的工作原理及其源代码。Tomcat作为一款广泛应用的开源Servlet容器,其内部机制对于优化Web...
《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Servlet和JSP规范。源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的...
《深入剖析Tomcat》这本书是Java开发者们探索Web服务器内部工作原理的重要参考资料,它详细解析了Tomcat的源代码,帮助我们理解这个流行的开源Servlet容器的运作机制。Tomcat是Apache软件基金会的一个项目,它是Java...
tomcat5 源码学习,深度剖析tomcat一书的指定tomcat版本,随着tomcat版本的升级,内容发生 了变化,但为了读懂书籍,还是得使用老版本得源码,欢迎大家下载,官网下载会出现下载不了的情况,我主页有tomcat4-tomcat9...
### Tomcat源码研究知识点概览 #### 1.1 Catalina.bat脚本解析 - **脚本功能**:`catalina.bat`是Tomcat启动过程中的关键脚本之一,其主要作用在于构建合适的Java命令行参数,进而启动Tomcat服务。此脚本根据环境...
本资源摘要信息涵盖了 Java 后端开发的多个方面,包括 JPA 防踩坑姿势、Servlet 3 异步原理与实践、Tomcat 源码剖析、Java 并发编程、Java 线程池、AbstractQueuedSynchronizer、Tomcat 系列、Netty 系列、Kafka ...
《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Web应用服务器标准,尤其是Servlet和JSP规范。源码下载是开发者深入理解其内部工作原理的重要途径,本篇文章将围绕...
带目录的《深入剖析TOMCAT》中文版,带目录,便于大家阅读
总的来说,《深入剖析Tomcat源码》这本书将带领我们探索Tomcat的每一个角落,从基础架构到高级特性,全面解析其设计思想和实现细节,帮助开发者更好地理解和优化自己的Java Web应用。通过学习和研究Tomcat源码,我们...
【描述】中的“深入剖析Tomcat”是一本引导读者进行Tomcat源码阅读的书籍,通过这本书,你可以了解到Tomcat是如何处理HTTP请求,如何管理Web应用,以及如何进行线程调度等核心功能的。这本书的推荐表明,作者认为它...
深入学习Tomcat源码,有助于我们掌握以下关键知识点: 1. **Servlet生命周期**:理解Servlet的初始化、服务、销毁过程,以及Tomcat如何管理和调度Servlet实例。 2. **容器结构**:Tomcat的容器模型包括Engine...