Tomcat 路由請求的實現 Mapper

2021-09-21 05:45:11 字數 2580 閱讀 3217

收到客戶端請求後,容器根據請求 url 的上下文名稱匹配 web 應用程式,然後根據去除上下文路徑和路徑引數的路徑,按以下規則順序匹配,並且只使用第乙個匹配的 servlet,後續不再嘗試匹配:

精確匹配,查詢乙個與請求路徑完全匹配的 servlet

字首路徑匹配,遞迴的嘗試匹配最長路徑字首的 servlet,通過使用 「/」 作為路徑分隔符,在路徑樹上一次乙個目錄的匹配,選擇路徑最長的

副檔名匹配,如果 url 最後一部分包含副檔名,如 .jsp,則嘗試匹配處理此副檔名請求的 servlet

如果前三個規則沒有匹配成功,那麼容器要為請求提供乙個預設 servlet

容器在匹配時區分大小寫。

在 web.xml 部署描述符中,使用以下語法定義對映:

假設有以下對映配置:

/foo/bar/*      servlet1

/baz/* servlet2

/catalog servlet3

*.bop servlet4

那麼以下請求路徑的匹配情況是:

/foo/bar/index.html      servlet1

/foo/bar/index.bop servlet1

/baz servlet2

/baz/index.html servlet2

/catalog servlet3

/catalog/index.html default servlet

/catalog/racecar.bop servlet4

/index.bop servlet4

注意,在 /catalog/index.html 和 /catalog/racecar.bop 的情況下,不使用對映到 /catalog 的 servlet,是因為不是完全匹配。

上圖包含了各類的核心成員變數和方法,也直觀的體現了類之間的關係。

protected

void

boolean jspwildcard)

else if (path.startswith("*.")) else if (path.equals("/")) else

}}

上文的 servlet 對映例項的配置,在記憶體中,儲存情況如下:

private

static

final

intfind

(mapelement[

] map, string name)

// 或者小於陣列的第乙個元素,那麼返回 -1 表示沒找到

if(name.

compareto

(map[0]

.name)

<0)

// 或者大於陣列的第乙個元素,且陣列長度為 1,返回下標 0

if(b ==0)

// 二分查詢等於或長度最接近 name 的陣列元素下標

int i =0;

while

(true

)else

if(result ==0)

elseif(

(b - a)==1

)else}}

}

以上文對映例項的配置為例,分析 /foo/bar/index.html 對映 servlet 的原始碼實現,注意這裡使用的路徑,要去除上下文路徑和路徑引數。

首先嘗試完全匹配:

// rule 1 -- exact match

;private

final

void(.

..)}

如果完全匹配失敗,然後嘗試最長路徑的模糊匹配,核心**如下:

// rule 2 -- prefix match

boolean checkjspwelcomefiles =

false

;// 確保完全匹配失敗

ifprivate

final

void(.

..)else

if(path.

startswithignorecase

("/"

, length))}

}// 這裡的 path 是 /foo/bar/index.html,符合第二個 if

if(found)

}

|-- context path --|-- servlet path -|--path info--|

|-------- request uri ----------------------------|

看原始碼時,發現 tomcat 寫了大量的**,那是因為,它為了減少記憶體拷貝,設計了乙個 charchunk,在乙個 char 陣列檢視上,實現了類似 string 的一些比較方法。

javascript實現java中的map

map.js function map linkitems 獲取當前map return 當前物件 map.noop function 非法操作 return map.illegal function param obj param foreignkeys return map.from funct...

路由的基本實現 hash路由

vue react在路由的實現上,都有基於hash的路由。那麼如何使用原生來實現呢?比如類似下面這樣的路由 hash實現路由的時候,最本質的原理就是hash值的變化,會引發乙個hashchange事件,可以根據這個hash值的變化,載入不同的dom。html divclass box flex bo...

tomcat獲得(Nginx前端)請求的真實位址

使用nginx如何配置tomcat訪問日誌記錄真實ip 收藏 使用nginx作為反向 時,tomcat的日誌記錄的客戶端ip就不在是真實的客戶端ip,而是nginx 的ip。要解決這個問題可以在nginx配置乙個新的header,用來儲存 remote add,然後再tomcat獲取記錄這個值。1....