如果在spring-mvc.xml 攔截方式如下配置:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 可以自定義servlet.xml配置文件的位置和名稱,默認(rèn)為WEB-INF目錄下,名稱為[<servlet-name>]-servlet.xml,如spring-servlet.xml
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value> 默認(rèn)
</init-param>
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Spring配置 -->
<listener>
<listenerclass>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 指定Spring Bean的配置文件所在目錄。默認(rèn)配置在WEB-INF目錄下 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/applicationContext.xml</param-value>
</context-param>
那么,所有的請(qǐng)求都會(huì)被攔截。包括靜態(tài)資源!
'/' 將會(huì)替換掉容器的default servlet, 將會(huì)處理所有其他handler(Servlet)都不處理的訪問請(qǐng)求.
如果web.xml沒有配置其他特殊路徑的servlet, 基本上所有的請(qǐng)求都交由DispatcherServlet處理.
將不會(huì)再訪問容器中原始默認(rèn)的servlet(你對(duì)靜態(tài)資源的訪問就是通過容器默認(rèn)servlet處理的),故而靜態(tài)資源將不可訪問??!
如果想要解決訪問靜態(tài)資源問題,通常會(huì)使用默認(rèn)handler:
<mvc:default-servlet-handler/>
該標(biāo)簽的xsd文檔說明如下:
/*配置一個(gè)handler通過轉(zhuǎn)發(fā)到servlet容器的默認(rèn)servlet來處理靜態(tài)資源*/
Configures a handler for serving static resources by forwarding to the Servlet container's default Servlet.
/*使用該handler允許DispatcherServlet 的url-patter 為'/',同時(shí)仍然使用servlet讓其去處理靜態(tài)資源*/
Use of this handler allows using a '/' mapping with the DispatcherServlet while still utilizing the Servlet container to serve static resources.
/*該handler將會(huì)轉(zhuǎn)發(fā)所有的請(qǐng)求到默認(rèn)serlvet*/
This handler will forward all requests to the default Servlet.
/*所以,在所有的URL HandlerMappings中,該handler對(duì)應(yīng)的mapping應(yīng)該留置最后!*/
Therefore it is important that it remains last in the order of all other URL HandlerMappings.
/*你可以使用兩種方式去保證你的handlermapping 的order屬性值小于DefaultServletHttpRequestHandler 對(duì)應(yīng)的handlermapping的order屬性值:使用<mvc:annotation-driven/>標(biāo)簽或者手動(dòng)配置HandlerMapping實(shí)例并設(shè)置其order屬性值*/
That will be the case if you use the 'annotation-driven' element
or alternatively if you are setting up your customized HandlerMapping instance
be sure to set its 'order' property to a value lower
than that of the DefaultServletHttpRequestHandler, which is Integer.MAX_VALUE.
新的問題出現(xiàn)了,你會(huì)發(fā)現(xiàn)以前的Controller不能訪問了?。?!
那么為什么會(huì)出現(xiàn)這個(gè)情況?
default-servlet-handler
將在SpringMVC上下文中定義一個(gè)DefaultServletHttpRequestHandler。
DefaultServletHttpRequestHandlerj的avadoc如下:
/*使用servlet容器的默認(rèn)servlet處理靜態(tài)資源*/
* An {@link HttpRequestHandler} for serving static files using the Servlet container's 'default' Servlet.
*
/*當(dāng)DispatcherServlet url-pattern為 ‘/’時(shí),該handler將會(huì)使用‘/*’去匹配請(qǐng)求路徑;因此,重置了servlet容器對(duì)靜態(tài)資源的默認(rèn)處理*/
* <p>This handler is intended to be used with a '/*' mapping when the
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
* is mapped to '/', thus overriding the Servlet container's default handling of static resources.
/*匹配該handler的mapping 應(yīng)該是最后到達(dá),當(dāng)沒有其他mapping可以處理請(qǐng)求時(shí)才會(huì)執(zhí)行該handler匹配的mapping。*/
* The mapping to this handler should generally be ordered as the last in the chain so that it will
* only execute when no other more specific mappings (i.e., to controllers) can be matched.
即,當(dāng)DispatcherServlet url-pattern為 ‘/’時(shí),該handler將會(huì)使用‘/*’去匹配請(qǐng)求路徑。
參考servlet的url-pattern規(guī)則可知 ‘/*’可以攔截一切請(qǐng)求。因?yàn)椤?’將servlet定義為默認(rèn)serlvet,在沒有精確匹配servlet出現(xiàn)前,’/*'
將擁有最高的優(yōu)先級(jí)?。?/p>
這是很嚴(yán)重的,/*
可以攔截路徑和資源型的請(qǐng)求,并轉(zhuǎn)發(fā)到默認(rèn)的serlvet?。?!
也就是說,靜態(tài)資源此時(shí)可以由默認(rèn)default servlet進(jìn)行處理,但是default servlet不能處理你的業(yè)務(wù)請(qǐng)求(mapping)?。?/p>
所以,需要保證該handler對(duì)應(yīng)的handler mapping在執(zhí)行順序中為最后!??!
解決辦法:
<mvc:annotation-driven />
至于為什么這樣解決,查看<mvc:default-servlet-handler/>
的xsd說明文檔就明白了。
點(diǎn)擊查看 <mvc:annotation-driven />
詳解annotation-driven詳解
點(diǎn)擊查看處理靜態(tài)資源的幾種方式springmvc處理靜態(tài)資源的幾種方式
【三種情況下的handlerAdapters:】
其中 AnnotationMethodHandlerAdapter是過期類,3.2之后被RequestMappingHandlerAdapter替代。
測(cè)試結(jié)果:1 3 可以正常流轉(zhuǎn),2 將找不到對(duì)應(yīng)方法。
【Tips:】DispatcherServlet不攔截jsp請(qǐng)求
前面說的當(dāng)DispatcherServlet配置為’/’, 將會(huì)覆蓋default servlet, 將會(huì)處理所有其他Servlet都不處理的訪問請(qǐng)求.
所以這里不攔截?cái)r截.jsp, .jspx.的請(qǐng)求, 一定有其他地方攔截了該請(qǐng)求, 但是仔細(xì)查找web.xml并沒有發(fā)現(xiàn)其他的servlet,那一定是在容器中定義的。
果不其然, 在%TOMCAT_HOME%/conf/web.xml中繼承過來的JspServlet會(huì)處理該請(qǐng)求.
該xml配置了兩個(gè)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>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
這也就是為什么我們直接訪問不在WEB-INF的jsp, 可以直接找到并解析的原因了.
聯(lián)系客服