做了2年多的J2EE開發,今天在看博客的時候看到這句話“如果你還不知道 web.xml 中一個請求和一個 servlet 是如何匹配到一起的,那麼請搜索一下 servlet 的文檔。這可不是亂說呀,有很多人就認爲 /xyz/*.do 這樣的匹配方式能有效”...我倒了
馬上做了相關測試,發現web.xml如下
<servlet> <servlet-name>test</servlet-name> <servlet-class>com.koa.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>test</servlet-name> <url-pattern>/test/*.do</url-pattern> </servlet-mapping>
在啓動服務器時就報錯了。。。
Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> /test/*.do in servlet mapping at org.apache.catalina.core.StandardContext.addServletMapping(StandardContext.java:3245) at org.apache.catalina.core.StandardContext.addServletMapping(StandardContext.java:3220) at org.apache.catalina.deploy.WebXml.configureContext(WebXml.java:1367) |
然後去搜索下關於請求是怎麼匹配servlet的
servlet容器對url的匹配過程: 當一個請求發送到servlet容器的時候,容器先會將請求的url減去當前應用上下文的路徑作爲servlet的映射url,比如我訪問的是http://localhost/test/aaa.html ,我的應用上下文是test,容器會將http://localhost/test 去掉,剩下的/aaa.html部分拿來做servlet的映射匹配。這個映射匹配過程是有順序的,而且當有一個servlet匹配成功以後,就不會去理會剩下的servlet了。其匹配規則和順序如下:
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