首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Tomcat源码系列3-Tomcat请求处理的流程

2012-08-21 
Tomcat源码系列3--Tomcat请求处理的流程本次讲解一下Tomcat请求处理的流程,不当之处还请comment。一. Tomca

Tomcat源码系列3--Tomcat请求处理的流程

本次讲解一下Tomcat请求处理的流程,不当之处还请comment。


一. Tomcat 总体结构
Tomcat采用模块化管理,下面是 Tomcat 的总体结构图:

Tomcat源码系列3-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处理请求的流程大致如下:

Tomcat源码系列3-Tomcat请求处理的流程
?
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源码系列3-Tomcat请求处理的流程
?
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()方法被调用。

?

热点排行