天天看點

Request URI = context path + servlet path + path info

|-- Context Path --|-- Servlet Path -|--Path Info--|
http://www.servername.com     /mywebapp        /helloServlet      /hello
                        |-------- Request URI  ----------------------------|


1. Context paths and servlet paths start with a / but do not end with it.
2. HttpServletRequest provides three methods getContextPath(),getServletPath() and getPathInfo() to retrieve 
   the context path, the servlet path, and the path info, respectively, associated with a request.

Identifying the servlet path
To match a request URI with a servlet, the servlet container follows a simple algorithm.
Once it identifies the context path, if any, it evaluates the remaining part of the
request URI with the servlet mappings specified in the deployment descriptor, in the
following order. If it finds a match at any step, it does not take the next step.1 The container tries to match the request URI to a servlet mapping. If it finds a
match, the complete request URI (except the context path) is the servlet path. In
this case, the path info is null.
2 It tries to recursively match the longest path by stepping down the request URI
path tree a directory at a time, using the / character as a path separator, and determining
if there is a match with a servlet. If there is a match, the matching part
of the request URI is the servlet path and the remaining part is the path info.
3 If the last node of the request URI contains an extension (.jsp, for example),
the servlet container tries to match it to a servlet that handles requests for the
specified extension. In this case, the complete request URI is the servlet path
and the path info is null.
4 If the container is still unable to find a match, it will forward the request to the
default servlet. If there is no default servlet, it will send an error message indicating
the servlet was not found.

1.     精确路徑比對。例子:比如servletA 的url-pattern為 /test,servletB的url-pattern為 /* ,這個時候,如果通路的url為http://localhost/test ,這個時候容器就會先進行精确路徑比對,發現/test正好被servletA精确比對,那麼就去調用servletA,也不會去理會其他的servlet了。 
2.     最長路徑比對。例子:servletA的url-pattern為/test/*,而servletB的url-pattern為/test/a/*,此時通路http://localhost/test/a時,容器會選擇路徑最長的servlet來比對,也就是這裡的servletB。 
3.     擴充比對,如果url最後一段包含擴充,容器将會根據擴充選擇合适的servlet。例子:servletA的url-pattern:*.action 
4.     如果前面三條規則都沒有找到一個servlet,容器會根據url選擇對應的請求資源。如果應用定義了一個default servlet

為什麼定義”/*.action”這樣一個看起來很正常的比對會錯?因為這個比對即屬于路徑映射,也屬于擴充映射,導緻容器無法判斷。