Tomcat學習之Request/Response封裝

org.apache.coyote.Request和org.apache.coyote.Response

在Acceptor接收到一個socket之後,在JIoEndpoint的processSocket方法中這個socket被包裝成SocketWrapper

  1. protected boolean processSocket(Socket socket) {  
  2.     // Process the request from this socket  
  3.     try {  
  4.         SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);  
  5.         wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());  
  6.         // During shutdown, executor may be null - avoid NPE  
  7.         if (!running) {  
  8.             return false;  
  9.         }  
  10.         getExecutor().execute(new SocketProcessor(wrapper));  
  11.     } catch (RejectedExecutionException x) {  
  12.         log.warn("Socket processing request was rejected for:"+socket,x);  
  13.         return false;  
  14.     } catch (Throwable t) {  
  15.         ExceptionUtils.handleThrowable(t);  
  16.         // This means we got an OOM or similar creating a thread, or that  
  17.         // the pool and its queue are full  
  18.         log.error(sm.getString("endpoint.process.fail"), t);  
  19.         return false;  
  20.     }  
  21.     return true;  
  22. }  
然後從線程池中分配一個線程來處理這次請求,會調用Http11ConnectionHandler.process方法來處理,來看看這個process方法

  1. public SocketState process(SocketWrapper<S> socket,SocketStatus status) {  
  2. Processor<S> processor = connections.remove(socket.getSocket());  
  3.   
  4. ......  
  5. if (processor == null) {  
  6.     processor = createProcessor();  
  7. }  
  8.   
  9. ......  
  10. state = processor.process(socket);  
  11. ......  
在這個方法裏面如果處理器爲空,就調用createProcessor方法創建一個,創建processor時會產生兩個對象,分別是request,response,也就是說在接收到socket之後用戶的請求作了如下轉化:


處理用戶請求會調用Adapter.service方法,Adapter就是一個適配器,來看看service方法的簽名

  1. public void service(org.apache.coyote.Request req,org.apache.coyote.Response res)  

service方法規定了用戶請求必須被轉化爲org.apache.coyote.Request才能被容器處理,由於用戶請求多種多樣,將這些多種多樣的請求接口轉換爲一個統一的接口正是適配器模式所長,這以這裏採用了適配器模式。


org.apache.catalina.connector.Request和org.apache.catalina.connector.Response

我們知道servlet的service方法需要傳入ServletRequest和ServletResponse類型的參數,tomcat是不是直接將org.apache.coyote.Request直接轉換爲ServletRequest了呢?從org.apache.coyote.Request沒有實現javax.servlet.http.HttpServletRequest接口可知不是這樣的。事實上也不能這樣做,因爲org.apache.coyote.Request裏面封閉了很多底層處理方法,不想暴露給web開發人員使用。所以org.apache.coyote.Request與ServletRequest之前還有一箇中間層,這就是tomcat容器獨有的請求響應接口:org.apache.catalina.connector.Request與org.apache.catalina.connector.Response

正如所料,在Adapter的service方法中將org.apache.coyote.Request轉化爲了org.apache.catalina.connector.Request,如下代碼所示:

  1. public void service(org.apache.coyote.Request req,org.apache.coyote.Response res)throws Exception {  
  2.     Request request = (Request) req.getNote(ADAPTER_NOTES);  
  3.     Response response = (Response) res.getNote(ADAPTER_NOTES);  
  4.   
  5.     if (request == null) {  
  6.         request = connector.createRequest();  
  7.         request.setCoyoteRequest(req);  
  8.         response = connector.createResponse();  
  9.         response.setCoyoteResponse(res);  
  10.   
  11.         request.setResponse(response);  
  12.         response.setRequest(request);  
  13.   
  14.         req.setNote(ADAPTER_NOTES, request);  
  15.         res.setNote(ADAPTER_NOTES, response);  
  16.     }  
  17.     ......  
  18. }  

org.apache.catalina.connector.Request實現了HttpServletRequest接口,重寫了父類的一些方法,還加了一些與容器相關的方法,另外還代理了org.apache.coyote.Request裏面的一些方法,既然org.apache.catalina.connector.Request裏面有一些容器特有的方法,這些方法也是不能給web開發人員使用的,那麼org.apache.catalina.connector.Request又是怎麼轉換爲ServletRequest的呢?這裏採用了外觀模式,將與容器相關的方法封裝起來。

  1. public class RequestFacade implements HttpServletRequest {     
  2.     protected Request request = null;  
  3.       
  4.     public RequestFacade(Request request) {  
  5.         this.request = request;  
  6.     }  
  7. }  
  8.   
  9. public class ResponseFacade implements HttpServletResponse {  
  10.     protected Response response = null;  
  11.       
  12.     public ResponseFacade(Response response) {  
  13.          this.response = response;  
  14.     }  
  15. }  
這些接口和類的關係圖如下:


本節只分析了request和response的類層次結構,具體請求的處理在後面分析!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章