<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### 請求定位Servlet的過程 一個請求是如何定位到讓哪個`Wrapper`的`Servlet`處理的?答案是,Tomcat 是用 Mapper 組件來完成這個任務的。 `Mapper`組件的功能就是將用戶請求的`URL`定位到一個`Servlet`,它的工作原理是:`Mapper`組件里保存了 Web 應用的配置信息,其實就是**容器組件與訪問路徑的映射關系**,比如`Host`容器里配置的域名、`Context`容器里的`Web`應用路徑,以及`Wrapper`容器里`Servlet`映射的路徑,你可以想象這些配置信息就是一個多層次的`Map`。 當一個請求到來時,`Mapper`組件通過解析請求 URL 里的域名和路徑,再到自己保存的 Map 里去查找,就能定位到一個`Servlet`。請你注意,一個請求 URL 最后只會定位到一個`Wrapper`容器,也就是一個`Servlet` ![](https://img.kancloud.cn/87/bb/87bbe3aa7d90ff2ec69fd090f22c3c01_1564x1140.png) 假如有用戶訪問一個 URL,比如圖中的`http://user.shopping.com:8080/order/buy`,Tomcat 如何將這個 URL 定位到一個 Servlet 呢? 1. **首先根據協議和端口號確定 Service 和 Engine**。Tomcat 默認的 HTTP 連接器監聽 8080 端口、默認的 AJP 連接器監聽 8009 端口。上面例子中的 URL 訪問的是 8080 端口,因此這個請求會被 HTTP 連接器接收,而一個連接器是屬于一個 Service 組件的,這樣 Service 組件就確定了。我們還知道一個 Service 組件里除了有多個連接器,還有一個容器組件,具體來說就是一個 Engine 容器,因此 Service 確定了也就意味著 Engine 也確定了。 2. **根據域名選定 Host。**Service 和 Engine 確定后,Mapper 組件通過 URL 中的域名去查找相應的 Host 容器,比如例子中的 URL 訪問的域名是`user.shopping.com`,因此 Mapper 會找到 Host2 這個容器。 3. **根據 URL 路徑找到 Context 組件。**Host 確定以后,Mapper 根據 URL 的路徑來匹配相應的 Web 應用的路徑,比如例子中訪問的是 /order,因此找到了 Context4 這個 Context 容器。 4. **根據 URL 路徑找到 Wrapper(Servlet)。**Context 確定后,Mapper 再根據 web.xml 中配置的 Servlet 映射路徑來找到具體的 Wrapper 和 Servlet 連接器中的 Adapter 會調用容器的 Service 方法來執行 Servlet,最先拿到請求的是 Engine 容器,Engine 容器對請求做一些處理后,會把請求傳給自己子容器 Host 繼續處理,依次類推,最后這個請求會傳給 Wrapper 容器,Wrapper 會調用最終的 Servlet 來處理。那么這個調用過程具體是怎么實現的呢?答案是使用 Pipeline-Valve 管道。 `Pipeline-Valve`是責任鏈模式,責任鏈模式是指在一個請求處理的過程中有很多處理者依次對請求進行處理,每個處理者負責做自己相應的處理,處理完之后將再調用下一個處理者繼續處理,Valve 表示一個處理點(也就是一個處理閥門),因此`invoke`方法就是來處理請求的。 ~~~ public interface Valve { public Valve getNext(); public void setNext(Valve valve); public void invoke(Request request, Response response) } ~~~ 繼續看 Pipeline 接口 ~~~ public interface Pipeline { public void addValve(Valve valve); public Valve getBasic(); public void setBasic(Valve valve); public Valve getFirst(); } ~~~ `Pipeline`中有`addValve`方法。Pipeline 中維護了`Valve`鏈表,`Valve`可以插入到`Pipeline`中,對請求做某些處理。我們還發現 Pipeline 中沒有 invoke 方法,因為整個調用鏈的觸發是 Valve 來完成的,`Valve`完成自己的處理后,調用`getNext.invoke()`來觸發下一個 Valve 調用。 其實每個容器都有一個 Pipeline 對象,只要觸發了這個 Pipeline 的第一個 Valve,這個容器里`Pipeline`中的 Valve 就都會被調用到。但是,不同容器的 Pipeline 是怎么鏈式觸發的呢,比如 Engine 中 Pipeline 需要調用下層容器 Host 中的 Pipeline。 這是因為`Pipeline`中還有個`getBasic`方法。這個`BasicValve`處于`Valve`鏈表的末端,它是`Pipeline`中必不可少的一個`Valve`,負責調用下層容器的 Pipeline 里的第一個 Valve ![](https://img.kancloud.cn/d5/2d/d52d76bfad67c7c1060aade58a126c79_1550x1160.png) 整個過程分是通過連接器中的`CoyoteAdapter`觸發,它會調用 Engine 的第一個 Valve: ``` @Override public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) { // 省略其他代碼 // Calling the container connector.getService().getContainer().getPipeline().getFirst().invoke( request, response); ... } ``` Wrapper 容器的最后一個 Valve 會創建一個 Filter 鏈,并調用`doFilter()`方法,最終會調到`Servlet`的`service`方法。 前面我們不是講到了`Filter`,似乎也有相似的功能,那`Valve`和`Filter`有什么區別嗎?它們的區別是: * `Valve`是`Tomcat`的私有機制,與 Tomcat 的基礎架構`API`是緊耦合的。`Servlet API`是公有的標準,所有的 Web 容器包括 Jetty 都支持 Filter 機制。 * 另一個重要的區別是`Valve`工作在 Web 容器級別,攔截所有應用的請求;而`Servlet Filter`工作在應用級別,只能攔截某個`Web`應用的所有請求。如果想做整個`Web`容器的攔截器,必須通過`Valve`來實現
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看