天天看點

Servlet的url詳解

【Servlet的url詳解】

url比對優先級:精确比對 > 以/開頭的比對 >以*開頭的比對。總之比對越精确,優先級越高。

<!-- 建立一個Serlvet對象  相當于Hello demo =new Hello() -->
  <servlet>
    <servlet-name>demo</servlet-name>
    <servlet-class>HelpServlet</servlet-class>
  </servlet>
  <!--  定義如何在浏覽器中通路此serlvet 如下即:通過/abc可以通路到demo類去處理-->  
  <servlet-mapping>
    <servlet-name>demo</servlet-name>
    <url-pattern>/abc.gdy</url-pattern> <!--規定隻能http://ip:端口/abc.gdy符合這樣的規則的url才能調用demo類型,在上面demo定義的類型是HelpServlet -->
  </servlet-mapping>

  <!-- 
<span style="white-space:pre">  </span>URl定義的寫法有一下幾種<span style="white-space:pre">  </span>注意URL的比對有優先級,越清楚的會優先比對,
 比如【/abc/ddd】這個請求【/】與【/*】會比對到,但會配置設定給【/*】,
 如果你還定義了一個【/abc/*】那麼會比對到【abc/*】來請求。

<span style="white-space:pre">  </span>以/開頭:/代表的是工程路徑(/工程名稱)必須要加/
<span style="white-space:pre">  </span>以*開頭:必須要加字尾名(字尾名任意)字尾名不能用*

<span style="white-space:pre">  </span>1.【/】比對帶有/的請求。
<span style="white-space:pre">  </span>2.【/abc/bbb】 會比對帶有/abc/bbb結尾的請求,去交個定義的内處理。
<span style="white-space:pre">  </span>3.【*.do】所有以.do結尾的url都會被比對到。
   --><span style="font-family: Arial, Helvetica, sans-serif;"> 
<welcome-file-list>
</span><span style="font-family: Arial, Helvetica, sans-serif;">    <welcome-file>login.html</welcome-file>
</span><span style="font-family: Arial, Helvetica, sans-serif;">  </welcome-file-list></span>      

一、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。

  另外,關于url-pattern映射之後, request的servletContextPath , ServletPath , PathInfo 情況,​​​​