Servlet映射規則和Servlet的映射URL沖突時匹配原則

分類:IT技術 時間:2017-03-25

一.url-pattern中通配符*的使用規則:

   (1)同一個Servlet可以被映射到多個URL上,即多個<servlet-mapping>元素的<servlet-name>子元素的設置值可以是同一個Servlet的註冊名。  
   (2)在Servlet映射到的URL中也可以使用*通配符,但是只能有兩種固定的格式:一種格式是“*.擴展名”, 另一種格式是以正斜杠(/)開頭並以“/*”結尾。
<servlet-mapping>
    <servlet-name>AnyName</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>AnyName</servlet-name>
    <url-pattern>/action/*</url-pattern>
</servlet-mapping>

 

二、servlet容器對url的匹配過程:

     當一個請求發送到servlet容器的時候,容器先會將請求的url減去當前應用上下文的路徑作為servlet的映射url,比如我訪問的是http://localhost/test/aaa.html,我的應用上下文是test,容器會將http://localhost/test去掉,剩下的/aaa.html部分拿來做servlet的映射匹配。這個映射匹配過程是有順序的,而且當有一個servlet匹配成功以後,就不會去理會剩下的servlet了(filter不同,後文會提到)。其匹配規則和順序如下: 

   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,則容器會將請求丟給default servlet(什麽是default servlet?請見:web.xml文件中缺省映射路徑"/"問題以及客戶端訪問web資源的匹配規則)。 

     根據這個規則表,就能很清楚的知道servlet的匹配過程,所以定義servlet的時候也要考慮url-pattern的寫法,以免出錯。 

     對於filter,不會像servlet那樣只匹配一個servlet,因為filter的集合是一個鏈,所以只會有處理的順序不同,而不會出現只選擇一個filter。Filter的處理順序和filter-mapping在web.xml中定義的順序相同。 
   

 三、url-pattern詳解 

   在web.xml文件中,以下語法用於定義映射: 

   l.以”/’開頭以”/*”結尾的是用來做路徑映射的。

   2.以前綴”*.”開頭的是用來做擴展映射的。 

   3. “/” 是用來定義default servlet映射的。 

   4. 剩下的都是用來定義詳細映射的。比如: /aa/bb/cc.action 

   所以,為什麽定義”/*.action”這樣一個看起來很正常的匹配在啟動tomcat時會報錯?因為這個匹配即屬於路徑映射,也屬於擴展映射,導致容器無法判斷

 四.示例(*.do的優先級別最低)

   對於如下的一些映射關系:
     Servlet1 映射到 /abc/* 
     Servlet2 映射到 /* 
     Servlet3 映射到 /abc 
     Servlet4 映射到 *.do 
  問題:
   當請求URL為“/abc/a.html”,“/abc/*”和“/*”都匹配,哪個servlet響應?
      Servlet引擎將調用Servlet1。
   當請求URL為“/abc”時,“/abc/*”和“/abc”都匹配,哪個servlet響應?
      Servlet引擎將調用Servlet3。
   當請求URL為“/abc/a.do”時,“/abc/*”和“*.do”都匹配,哪個servlet響應?
      Servlet引擎將調用Servlet1。
   當請求URL為“/a.do”時,“/*”和“*.do”都匹配,哪個servlet響應?
      Servlet引擎將調用Servlet2。
   當請求URL為“/xxx/yyy/a.do”時,“/*”和“*.do”都匹配,哪個servlet響應?
    Servlet引擎將調用Servlet2.

 


Tags: localhost filter action 上下文 擴展名

文章來源:


ads
ads

相關文章
ads

相關文章

ad