Servlet規範之URL對映
對映請求到Servlet
|-- Context Path --|-- Servlet Path -|--Path Info--|
http://www.myserver.com /mywebapp /helloServlet /hello
|-------- Request URI ----------------------------|
引導servlet服務請求的請求路徑由許多重要部分組成。以下元素從請求URI路徑得到,並通過request物件公開:
- Context Path:與ServletContext相關聯的路徑字首是這個servlet的一部分。如果這個上下文是基於Web伺服器的URL名稱空間基礎上的“預設”上下文,那麼這個路徑將是一個空字串。否則,如果上下文不是基於伺服器的名稱空間,那麼這個路徑以/字元開始,但不以/字元結束。
- Servlet Path:路徑部分直接與啟用請求的對映對應。這個路徑以“/”字元開頭,如果請求與“/ *”或“”模式匹配,在這種情況下,它是一個空字串。
- PathInfo:請求路徑的一部分,不屬於Context Path或Servlet Path。如果沒有額外的路徑,它要麼是null,要麼是以’/’開頭的字串。
使用HttpServletRequest介面中的下面方法來訪問這些資訊:
- getContextPath
- getServletPath
- getPathInfo
重要的是要注意,除了請求URI和路徑部分的URL編碼差異外,下面的等式永遠為真:
requestURI = contextPath + servletPath + pathInfo
在web.xml中設定下述的Servlet對映規則
Context Path | /catalog | Servlet |
---|---|---|
Servlet Mapping | Pattern: /lawn/* | LawnServlet |
Servlet Mapping | Pattern: /garden/* | GardenServlet |
Servlet Mapping | Pattern: *.jsp | JSPServlet |
得到的結果為
請求路徑 | ContextPath | ServletPath | PathInfo |
---|---|---|---|
/catalog/lawn/index.html | /catalog | /lawn | /index.html |
/catalog/garden/implements/ | /catalog | /garden | /implements/ |
/catalog/help/feedback.jsp | /catalog | /help/feedback.jsp | null |
servlet容器的url-pattern對映規範
在web應用部署描述符中,以下語法用於定義對映:
- 以‘/’字元開始、以‘/*’字尾結尾的字串用於路徑匹配。
- 以‘*.’開始的字串用於副檔名對映。
- 只包含“/”字元的字串用於default servlet對映。
- 其他字串僅用於精確匹配。
如果一個url-pattern設定的對映即屬於路徑對映,也屬於擴充套件對映(如:/*.action
),導致容器無法判斷,那麼部署將報錯。
default Servlet(預設Servlet)詳解
- web.xml中如果某個Servlet的對映路徑僅僅為一個正斜槓(/),那麼這個Servlet就成為當前Web應用程式的預設Servlet。
- 凡是在web.xml檔案中找不到匹配的
<servlet-mapping>
元素的URL,它們的訪問請求都將交給預設Servlet處理,也就是說,預設Servlet用於處理所有其他Servlet都不處理的訪問請求。 如果在web.xml中未設定一個default Servlet的時候,容器會設定一個容器自帶的Servlet。
- tomcat容器中會預設註冊了一個名稱為
org.apache.catalina.servlets.DefaultServlet
的Servlet - 當訪問Tomcat伺服器中的某個靜態HTML檔案和圖片時,實際上是在訪問這個預設Servlet,由DefaultServlet類尋找,當尋找到了請求的html或圖片時,則返回資源,如果沒有尋找到則報出404錯誤。
- tomcat容器中會預設註冊了一個名稱為
servlet容器對url的匹配過程
在收到客戶端請求時,web容器確定轉發到哪一個Web應用。選擇的Web應用必須具有最長的上下文路徑匹配請求URL的開始。當對映到Servlet時,URL匹配的一部分是上下文。
Web容器接下來必須用下面描述的路徑匹配步驟找出servlet來處理請求。
用於對映到Servlet的路徑是請求物件的請求URL減去上下文和路徑引數部分。下面的URL路徑對映規則按順序使用。使用第一個匹配成功的且不會進一步嘗試匹配:
- 容器將嘗試找到一個請求路徑到servlet路徑的精確路徑匹配。成功匹配則選擇該servlet。
- 容器將遞迴地嘗試最長路徑匹配。這是通過一次一個目錄的遍歷路徑樹完成的,使用‘/’字元作為路徑分隔符。最長匹配確定選擇的servlet。
- 如果URL最後一部分包含一個副檔名(如 .jsp),servlet容器嘗試擴充套件匹配,將檢視匹配為副檔名處理請求的Servlet。副檔名定義在最後一部分的最後一個‘.’字元之後。
- 如果前三個規則都沒有產生一個servlet匹配,容器將試圖為請求資源提供相關的內容。如果應用中定義了一個“default”servlet,它將被使用。許多容器提供了一種隱式的default servlet用於提供內容。
示例對映集合
Path Pattern | Servlet | 匹配模式 |
---|---|---|
/foo/bar/* | servlet1 | 最長路徑匹配 |
/baz/* | servlet2 | 最長路徑匹配 |
/catalog | servlet3 | 精確路徑匹配 |
*.bop | servlet4 | 擴充套件匹配 |
注意,精確路徑匹配是全字串匹配,最長路徑匹配是帶正則表示式的字串匹配。
將產生以下結果:
Incoming Path | Servlet Handling Request |
---|---|
/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,因為不是精確匹配的。