本次讲解一下Tomcat请求处理的流程,不当之处还请comment。
一. Tomcat 总体结构
Tomcat采用模块化管理,下面是 Tomcat 的总体结构图:
从上图中可以看出 Tomcat 的核心是两个组件:Connector 和 Container。下面是一些概念的介绍。
① Server
一个server代表了整个catalina servlet容器,在Tomcat里面的Server的用处是启动和监听服务端事件(诸如重启、关闭等命令)。
② Service
Service是由一个或多个Connector与一个Engine的组合。
③ Connector
Connector将在某个指定的端口上监听客户的请求,把从socket传递过来的数据,封装成Request,传递给Engine来处理,并从Engine处获得响应并返回给客户。
Tomcat通常会用到两种Connector:
a) Http Connector 在端口8080处侦听来自客户browser的http请求。
b) AJP Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求。
二、请求处理过程解析
1. Connector处理请求
Connector处理请求的流程大致如下:
Connector组件启动后,会侦听相关的端口的客户端请求。
(1) 接受一个新的连接请求(org.apache.tomcat.util.net.TcpWorkerThread)
void runIt(Object[] perThrData){
Socket s = null;
try {
s = endpoint.acceptSocket(); //获取一个请求
} finally {
if (endpoint.isRunning()) {
endpoint.tp.runIt(this);
// 此处启动另一个TcpWorkerTread去接受其他请求,此线程处理已接受的请求
}
}
TcpConnection con = null;
con = (TcpConnection) perThrData[0];
con.setEndpoint(endpoint);
con.setSocket(s);endpoint.getConnectionHandler().processConnection(con,(Object[]) perThrData[1]);
}
(2) 新接收的请求被传到Http11ConnectionHandler中处理。(org.apache.coyote.http11.Http11Protocol.Http11ConnectionHandler)
void processConnection(TcpConnection connection, Object[] thData){
Http11Processor processor=null;
processor=(Http11Processor)thData[Http11Protocol.THREAD_DATA_PROCESSOR];
socket=connection.getSocket();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
processor.setSocket(socket );
processor.process(in, out);
//processor是org.apache.coyote.http11.Http11Processor 的 一个实例
}
(3) 在 Http11Processor 中处理 http11 协议相关的信息(org.apache.coyote.http11.Http11Processor)
void process(InputStream input, OutputStream output) throws IOException{
~~略~~
inputBuffer.setInputStream(input);
outputBuffer.setOutputStream(output);
inputBuffer.parseHeaders();
//http11 协议头在此方法中被取出
adapter.service(request, response);
//adapter 是org.apache.catalina.connector.CoyoteAdapter 的 一个实例
}
接下来的流程交由容器进行处理。
2. 容器处理请求
容器交由Pipeline处理,这个Pipeline里面会放置一些vavle,请求沿着pipeline传递下去并且vavle对其进行相关的处理。比如说日志等,valve还可以自定义,具体需要查看server.xml配置文件。相关类图如下:
Tomcat的主要处理组件Engine、Host、Context和Wrapper的实现都会实现Pipeline接口,实际对请求的处理是一个Adpater,Tomcat中Adapter的实现是CoyoteAdapter,因此容器请求处理的入口是CoyoteAdapter的service方法。
1. CoyoteAdapter.service
--组装好请求处理链
--StandardEngine. getPipeline().getFirst().invoke(request, response);
--StandardEngineValve.invoke
2. StandardEngineValve.invoke
--Host.getPipeline().getFirst().invoke(request, response);
--StandardHostValve.invoke
3. StandardHostValve.invoke
--Context. getPipeline().getFirst().invoke(request, response);
--StandardContextValve.invoke
4. StandardContextValve.invoke
--ServletRequestListener.requestInitialized
--Wrapper.getPipeline().getFirst().invoke(request, response);
--StandardWrapperValve.invoke
-- ServletRequestListener.requestDestroyed
5. StandardWrapperValve.invoke
--组装Filter+Servlet
--处理请求
(1) Connector传来的请求调用CoyoteAdapter.service()方法。(org.apache.catalina.connector.CoyoteAdapter)
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
~~略~~
if (request == null) {
request = (Request) connector.createRequest();
request.setCoyoteRequest(req);
response = (Response) connector.createResponse();
response.setCoyoteResponse(res);
//创建request、response对象
~~略~~
}
try {
if (postParseRequest(req, request, res, response)) {
connector.getContainer().getPipeline().getFirst().invoke(request, response);
//此处的Container是StandardEngine对象
~~略~~
}
}
(2) 默认StandardEngine的Pipeline会有StandardEngineValve处理单元(参照StandardEngine构造函数)。(org.apache.catalina.core.StandardEngineValve)
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Select the Host to be used for this Request
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
// Ask this Host to process this request
host.getPipeline().getFirst().invoke(request, response);
}
(3) 同样的,StandardHost的Pipeline会有StandardHostValve处理单元。StandardHostValve如何处理请求跟StandardEngineValve类似,接下来请求进入到StandardContextValve.invoke
(4) 同样的,StandardContext的Pipeline会有StandardContextValve处理单元。
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// Disallow any direct access to resources under WEB-INF or META-INF MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
String requestURI = request.getDecodedRequestURI();
notFound(requestURI, response);
return;
}
// Wait if we are reloading
while (context.getPaused()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
}
}
// Select the Wrapper to be used for this Request
Wrapper wrapper = request.getWrapper();
if (wrapper == null) {
String requestURI = request.getDecodedRequestURI();
notFound(requestURI, response);
return;
}
//ServletRequestListener. requestInitialized
~~略~~
wrapper.getPipeline().getFirst().invoke(request, response);
//ServletRequestListener.requestDestroyed
~~略~~
}
(5) 同样的,StandardWrapper这个Pipeline会有StandardWrapperValve这个处理单元。在invoke()方法调用Filter的同时,servlet.service()方法也将会被调用。
(org.apache.catalina.core.StandardWrapperValve)
void invoke(Request request, Response response, ValveContext valveContext)
throws IOException, ServletException{
Servlet servlet = null;
HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
//org.apache.catalina.Request被封装成javax.servlet.http.HttpServletRequest.
HttpServletResponse hres =(HttpServletResponse) response.getResponse();
// org.apache.catalina.Response被封装成javax.servlet.http.HttpServletResponse.
servlet = wrapper.allocate(); // 装载servlet
if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(hreq, hres); //调用此servlet的filterchain
}
(6) 调用servlet的filterchain 处理 request和response
(org.apache.catalina.core.ApplicationFilterChain)
void doFilter(ServletRequest request, ServletResponse response) throws
IOException, ServletException{
~~略~~
internalDoFilter(request,response);
~~略~~
}
(7) 调用internalDoFilter()处理请求。(org.apache.catalina.core.ApplicationFilterChain)
void internalDoFilter(ServletRequest request, ServletResponse response) throws
IOException, ServletException{
// 此处省略filter 处理的代码,filter 被一个一个调用。
// 如果http请求的是一个jsp页面, 下面的 servlet 会是 org.apache.jasper.servlet.JspServlet 类的一个实例
// 若是 html 页面, 下面的 servlet 会是 org.apache.catalina.servlets.DefaultServlet 类的一个实例
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
servlet.service(request, response);
} else {
servlet.service(request, response);
}
}
至此,servlet.service()方法被调用。
- 大小: 10.5 KB
- 大小: 16.5 KB
- 大小: 19.9 KB
分享到:
相关推荐
3-5Tomcat响应请求源码与nio处理请求源码实现.mp4
apache-tomcat-9.0.8 其中有完整的源码 bin目录下有你所想要的所有完整的
从零手写Tomcat【源码】【abl-tomcat-004】【基础完善-处理动态资源请求】 文章地址:https://blog.csdn.net/m0_37969197/article/details/124096403 目录地址:...
从零手写Tomcat【源码】【abl-tomcat-005】【添加多线程,处理请求】 文章地址:https://blog.csdn.net/m0_37969197/article/details/124098639 目录地址:...
分析Tomcat请求过程 链接器(Connector)与容器(Container) 解耦 Connector设计 监听服务端口,读取来自客户端的请求 将请求数据按照指定协议进行解析 根据请求地址匹配正确的容器进行处理 将响应返回客户端 ...
3-8Tomcat请求容器中的处理与启动过程源码实现(1).mp4
在这里,会话被实现为非粘性的(意味着,每个请求都可以转到集群中的任何服务器,这与Apache提供的Tomcat集群设置不同。) 请求会话将立即存储到Redis中(会话属性必须是可序列化的),以供其他服务器使用。 当...
3-8Tomcat请求容器中的处理与启动过程源码实现(2).mp4
Tomcat初始化流程分析,Tomcat启动流程分析 Tomcat处理一次请求过程分析 servlet初始化流程
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台...
对 NIO 模式,请求的流程描述的很详细。值得去仔细的研究。
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台...
3. 并发性改进:Tomcat 8 对并发性进行了改进,包括更好的线程管理、请求处理和响应处理等方面的优化。 4. EL 3.0支持:Tomcat 8 支持最新的EL(表达式语言)3.0规范,提供了更多的表达式功能和语言特性。 5. JSP ...
版本:apache-tomcat-9.0.88 以下是一些 Tomcat 9 中新增的主要功能: 1. Servlet 4.0支持:Tomcat 9...6. WebSocket子协议支持:Tomcat 9 支持对 WebSocket 子协议的处理,允许服务器和客户端之间传输更多类型的数据。
1.web.xml内容修改,添加servlet标签 2.添加Servlet接口与实现 3.解析web.xml 4.修改启动时逻辑,扫描全部servlet 5.Request、Response 说明 6.动态处理请求,通过反射创建Servlet 7.浏览器测试
NULL 博文链接:https://liudeh-009.iteye.com/blog/1563948
资源是关于tomcat深入剖析的源码. 本书深入剖析Tomcat 4和Tomcat 5中的每个组件,并揭示其内部工作原理。通过学习本书,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。...
https原理及tomcat配置https方法;SSL加密传输;请求路径https://...;客户端需安装证书...
NULL 博文链接:https://yjhexy.iteye.com/blog/661491
Tomcat是一款servlet服务器,它能够接受请求,处理请求并给出响应。