springMVC 訪問靜態資源


問題描述  

使用SpringMVC時遇到靜態資源無法加載的問題,報404

問題原因

  如果SpringMVC的映射模式采用的是后綴名匹配,如【*.do】或者【*.action】則不會出現該問題,因為靜態資源的訪問會由tomcat的默認Servlet,即org.apache.catalina.servlets.DefaultServlet,進行處理。

  出現這種問題一般是在web.xml中的對spring的DispatcherServlet采用了如下配置,即url-pattern設置為了“/”(或"/*",這種匹配默認極其惡劣),這樣便要求SpringMVC負責處理靜態資源請求。

  

<!-- Spring MVC servlet -->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <!-- 此處可以可以配置成*.do,對應struts的后綴習慣 -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

  這種情況下瀏覽器的jsp請求能夠成功是以為Tomcat容器默認配置了jsp Servlet,如下。由於url-pattern是“.jsp”,屬於擴展名匹配,優先級高於“/”匹配,所以jsp Servlet會被容器調用,不會出現jsp資源無法獲取的問題。

  關於Servlet中url-pattern的配置和優先級問題,請參見博文servlet的url-pattern匹配規則

     <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 mappings for the JSP servlet -->
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

解決方法

1使用tomcat容器的默認servlet 處理靜態資源請求

在web.xml里添加如下的配置,由於后綴名匹配的優先級高於默認匹配規則(“/”),所以靜態資源請求會由DefaultServlet進行處理。

<servlet-mapping>
     <servlet-name>default</servlet-name>
     <url-pattern>*.css</url-pattern>
</servlet-mapping>
 
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.gif</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>

 

tomcat的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>false</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>

在spring的配置文件中添加<mvc:default-servlet-handler/>

<mvc:default-servlet-handler/>

  注意,需要是spring3.0.5以上版本

  該配置會在DispatcherServlet中注冊 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping,該類中又注冊了訪問路徑和對應的處理類,如下圖:

  /**  ->  org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler

  

  即最終由DefaultServletHttpRequestHandler完成靜態資源請求處理。

  這時SpringMVC便具備了處理靜態資源請求的能力。

  另外需要注意的是,由於<mvc:default-servlet-handler/> 標簽注冊了SimpleUrlHandlerMapping類,所以DispatcherServlet便不再默認注冊DefaultAnnotationHandlerMapping,也就無法處理RequestMapping等注解。解決方法就是手動在配置文件中配置DefaultAnnotationHandlerMapping bean,或者添加<mvc:annotation-driven/>標簽。

在spring的配置文件中添加<mvc:resources mapping="" location="" />

<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/" />

  該標簽和<mvc:default-servlet-handler/>類似,也會在DispatcherServlet中注冊 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping,不同的是每一條配置都會注冊一個SimpleUrlHandlerMapping到DispatcherServlet中,上例會注冊三個。

每個SimpleUrlHandlerMapping內部會生成一個映射,如<mvc:resources mapping="/js/**" location="/js/" />對應的SimpleUrlHandlerMapping內部映射為:

"/js/**" -> "ResourceHttpRequestHandler 

即最終由ResourceHttpRequestHandler 完成靜態資源請求的處理。

另外需要注意的是,使用<mvc:resources mapping="" location="" />后,也需要手動在配置文件中配置DefaultAnnotationHandlerMapping bean,或者添加<mvc:annotation-driven/>標簽。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM