Serlvlet路徑映射
當一個請求發送到servlet容器的時候,容器先會將請求的url減去當前應用上下文的路徑作為servlet的映射url。
容器默認請求的是一個Servlet,所以不會直接根據路徑從文件夾中查找文件,而是先從web.xml中根據<url-pattern>查找對應的Servlet文件,匹配成功后就停止繼續匹配;如果沒有找到,才會從文件夾中找。都沒有,則返回404。
匹配規則
url-pattern匹配規則只有以下五種(*為通配符):
■ 以“/”字符開頭,並以“/*”結尾的字符串用於路徑映射。
<url-pattern>/user/*</url-pattern>
http://localhost:5555/ myapp /user (也可以匹配到,*通配符相當於空)
http://localhost:5555/ myapp /user/addUser.action
http://localhost:5555/ myapp /user/updateUser.action
■ 以“*.”開頭的字符串被用於擴展名映射。
<url-pattern>*do</url-pattern>
http://localhost:5555/myapp/item/order.do
http://localhost:5555/myapp/user/test.do
■ 空字符串("")是用於指定精確映射應用程序 context root 的 URL 模式,比如從 http://host:port/<contextroot>/ 來的請求。在這種情況下路徑信息是“/”,servlet 路徑和 context 路徑是一個空的字符串("")。
■ 字符串中僅有“/”字符時,表示應用容器提供的默認servlet。在這種情況下 servlet 路徑是請求 URI 去掉 context 路徑且路徑信息為 null。
■ 其他類型的字符串都屬於精確匹配。url必須與<url-pattern>中的配置完全匹配。
<url-pattern>/user</url-pattern> <!—沒有/*結尾,屬於精確匹配規則->
匹配順序(匹配優先級):
精確匹配>路徑匹配(長路徑>短路徑)>擴展名匹配>default Servlet(/)
Tomcat按照上述順序依次將請求url和web.xml中的url-pattern進行匹配。
注意:
1.各匹配規則不能組合使用,以下同時設置路徑匹配和擴展名匹配都不正確:
<url-pattern>/kata/*.jsp</url-pattern>
<url-pattern>/*.jsp</url-pattern>
<url-pattern>he*.jsp</url-pattern>
<url-pattern>/user/*.action</url-pattern>
2. “/*”屬於路徑匹配,路徑就是/,可以匹配所有request。如果存在和請求對應的.jsp/.html文件,依然將請求發送給對應的servlet,導致404錯誤。該url-pattern一般只用於filter。
靜態資源處理
tomcat在${tomcat_home}/conf/web.xml中配置了default servlet,對靜態資源的請求容器會返回相應的資源文件:
<servlet> <servlet-name>default</servlet-name> <servlet-class> org.apache.catalina.servlets.DefaultServlet </servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> ... <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
如果開發者在web應用的web.xml中使用了<url-pattern>/</url-pattern>,會優先於tomcat內置的default servlet生效。該url-pattern匹配所有request,但優先級最低,用於處理其他Servlet都不處理的請求。即使存在和請求對應的靜態資源(.jsp除外),服務器仍然不會返回該靜態資源,而是將該請求轉給對應的Serlvet處理。
tomcat除了配置了default serlvlet,還內置了專門處理url-pattern為*.jspx和*.jsp的servlet,所以對.jsp的請求會返回對應的文件,除非出現優先級更高的url-pattern。
所以,為了使用SpringMVC而在web.xml中配置<url-pattern>/</url-pattern>,會導致靜態資源的404錯誤。可以用如下方式解決:
1.為靜態資源指定路徑匹配或擴展匹配以重新利用tomcat的default servlet返回靜態資源
<!--使用路徑匹配規則為整個靜態資源目錄映射--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping> <!--或者使用擴展名匹配規則--> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping>
這種方法不能訪問WEB-INF目錄下的靜態資源,靜態資源必須放在web應用的根目錄下和WEB-INF目錄平級,如上述的static目錄。
2.使用spring 3.0.4的新特性,在springmvc.xml中添加<mvc:resource>元素:
<mvc:resources location="/static/js/" mapping="/js/**" /> <mvc:resources location="/WEB-INF/js/" mapping="/js/**" />
這種方式可以引用WEB-INF目錄下的靜態資源。
3.在Springmvc.xml中配置<mvc:default-serlvet-handler>使用容器的default servlet,該標簽只對匹配規則為"/"的DispatcherServlet才生效。Springmvc會將請求轉發給default servlet,多一個流程,性能不如方法1。
<mvc:default-servlet-handler default-servlet-name = "default_servlet_name" />