前一篇博客,我總結了Tomcat對於生命週期組件的管理。在瞭解了容器的啓動以後,咱們開始剖析它的內部運行機制。今天咱們來分析一下Tomcat如何處理Request。Socket做爲網絡通訊的基礎也是Request和Response的底層實現,有過Socket使用經驗的讀者必定不會對下面的僞代碼陌生:apache
// Java僞代碼 ... while(true) { Socket soc = ServerSocket.accept(); // 監聽並阻塞 new Thread(new Runnable() { // 開闢新的線程處理Socket inputStream(soc); // 讀取Socket中的數據 outputStream(soc); // 寫入數據 }); } ...
1、從Socket到Request設計模式
Tomcat容器對Socket的處理思路與以上僞代碼基本一致,只是更加複雜。下圖展現了從Tomcat啓動到Socket到來後,主要類的調動過程(虛線箭頭表示有新的線程啓動):網絡
Acceptor是定義在JIoEndpoint中的內部類實現了Runnable接口。在run方法中定義了循環語句while (running){...}重點是ServerSocketFactory獲取監聽端口(默認8080)上的Socket請求app
Socket socket = null; try { // Accept the next incoming connection from the server // socket socket = serverSocketFactory.acceptSocket(serverSocket); ...
而後,這個Socket對象會被封裝成SocketWrapper對象並交給給JIoEndpoint的另外一個內部類SocketProcessor處理。socket
protected boolean processSocket(Socket socket) { // Process the request from this socket try { SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket); wrapper.setKeepAliveLeft(getMaxKeepAliveRequests()); wrapper.setSecure(isSSLEnabled()); ...
一直到AbstractHttp11Processor.process方法,咱們第一次見到了Request的身影。不過此時的Request其實是org.apache.coyote.Request,它是Tomcat內部的定義類而且被final修飾。在CoyoteAdapter.service方法中,它又被處理成:org.apache.catalina.connector.Request,它繼承了HttpServletRequest。直到這時,從Socket到Request才真正完成。函數
2、Pipeline、FilterChain以及設計模式this
ContainerBase是Tomcat中的生命週期組件。它包含了4個標準的實現類:StandardContext、StandardEngine、StandardHost和StandardWrapper。每個Container對象都含有各自的Pipeline和Valve。spa
/** * The Pipeline object with which this Container is associated. */ protected Pipeline pipeline = new StandardPipeline(this); /** * Create a new StandardContext component with the default basic Valve. */ public StandardContext() { super(); pipeline.setBasic(new StandardContextValve()); ... } ...
它們經過Container的構造函數被初始化,並負責處理Request。每個Containner組件都實現了各自的invoke方法,具體的業務邏輯讀者能夠本身去分析。線程
通過4次invoke,Request會繼續交給FilterChain(責任鏈模式的核心對象)處理。設計
ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet); try { if ((servlet != null) && (filterChain != null)) { if (context.getSwallowOutput()) { ... } else { if (request.isAsyncDispatching()) { ... } else if (comet) { ... } else { filterChain.doFilter(request.getRequest(), response.getResponse()); } } ...
通過多個Filter的處理,纔會交到Servlet的手中。