Spring MVC中處理靜態資源的多種方法

jopen 11年前發布 | 163K 次閱讀 Spring MVC Web框架

處理靜態資源,我想這可能是框架搭建完成之后Web開發的”頭等大事“了。

因為一個網站的顯示肯定會依賴各種資源:腳本、圖片等,那么問題來了,如何在頁面中請求這些靜態資源呢?

還記得Spring MVC中的DispatcherServlet嗎?它是Spring MVC中的前置控制器,若配置的攔截路徑為“/”,那么所有的請求都將被它攔截。對靜態資源的訪問也屬于一個請求,那么也會被它攔截,然后進入它的匹配流 程,我們知道它是根據HandlerMapping的配置來匹配的。而對于靜態資源來說,默認的Spring MVC是沒有注冊匹配規則的,此時若你去請求一個靜態資源,則會報404錯誤。

如何處理靜態資源的請求呢?

根據上面介紹的,我們可以配置一個處理靜態資源的HandlerMapping

    <bean id="resourceHttpRequestHandler" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">  
        <property name="locations" value="classpath:/META-INF/resources/"></property>     
    </bean>  

    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
        <property name="mappings">  
            <props>  
                <prop key="/resources/**">resourceHttpRequestHandler</prop>  
            </props>  
        </property>  
    </bean>  


其中ResourceHttpRequestHandler就是處理靜態資源請求的類,當然如果你愿意,也可以自己嘗試寫一個。

不過現在這樣自己寫SimpleUrlHandlerMapping比較少了吧,項目中都是采用的注解配置,只不過是將匹配關系放到注解上

另外,還可以使用mvc命名空間的resources標簽來配置

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


本質上也是把ResourceHttpRequestHandler注冊到SimpleUrlHandlerMapping上。

還有別的方法來處理靜態資源請求嗎?

Spring MVC還提供了一個配置項:mvc:default-servlet-handler

這個標簽對于匹配規則為"/"的DispatcherServlet才生效(因為別的匹配規則一般也不會攔截靜態資源)。它會為DefaultServletHttpRequestHandler配置上"/**"的攔截規則和最低的匹配優先級。

DefaultServletHttpRequestHandler處理請求時會將其全部轉發到容器的DefaultServlet上。因此它在 HandlerMapping必須是優先級最低的。如果你使用<mvc:annotation-driven>或你使用了自定義的 HandlerMapping實例,確保它們的order值比DefaultServletHttpRequestHandler小 (Integer.MAX)。

另外需要注意的是,這里尋找容器的DefaultServlet是用名字而不是路徑。所以首先要搞清楚容器的DefaultServlet的名字, 當然一般主流容器的名字是無需指定的,比如Tomcat, Jetty, JBoss, and GlassFish等。若非常用容器,則可能需要手動指定:

    <mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>  


這種方式也是依賴于容器的DefaultServlet的,那么我們是否能直接用容器的DefaultServlet來處理靜態資源請求,而不是這樣先通過Spring MVC來轉發呢?(相比性能上會好很多),答案是肯定的。

比如我們將資源文件都放在resouces目錄下,那么只需要在web.xml中配置:

    <servlet-mapping>  
        <servlet-name>default</servlet-name>  
        <url-pattern>/resource/*</url-pattern>  
    </servlet-mapping>  

并將它放在所有Servlet的最前面(為了讓它最先匹配),這樣的話性能上應該比較好

但是這樣還會有個問題,就是無法訪問到classpath下的資源文件,看了tomcat的DefaultServlet的配置項,似乎也沒有可以指定目錄的地方。

所以,綜上所述,性能最好的應該是直接利用容器的DefaultServlet,讓它最先攔截靜態資源請求,這樣就避免了后續的轉發等操作,提高了 性能,但是無法訪問classpath下的資源文件。而通過mvc:resources標簽可以簡單配置匹配規則和資源文件路徑,應該說是最簡單快捷的一 種方式,當然這大概也是mvc命名空間設計的初衷。

另外,若想結合兩者的話,自己倒是可以嘗試寫一個Servlet來處理,不過估計有難度且麻煩。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!