??? 一,
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
?后面會講)
。
|
?
???
根據這個規則表,就能很清楚的知道
servlet
的匹配過程,所以定義
servlet
的時候也要考慮
url-pattern
的寫法,以免出錯。
?????
對于
filter
,不會像
servlet
那樣只匹配一個
servlet
,因為
filter
的集合是一個鏈,所以只會有處理的順序不同,而不會出現只選擇一個
filter
。
Filter
的處理順序和
filter-mapping
在
web.xml
中定義的順序相同。
??? 二,url-pattern
詳解
???????? 在 web.xml 文件中,以下語法用于定義映射:
l? 以 ”/’ 開頭和以 ”/*” 結尾的是用來做路徑映射的。
l? 以前綴 ”*.” 開頭的是用來做擴展映射的。
l? “/” 是用來定義 default servlet 映射的。
l? 剩下的都是用來定義詳細映射的。比如: /aa/bb/cc.action
所以,為什么定義 ”/*.action” 這樣一個看起來很正常的匹配會錯?因為這個匹配即屬于路徑映射,也屬于擴展映射,導致容器無法判斷。