Tomcat和應用處理請求的級別和流程如下圖所示:
對資源的訪問地址爲:http://ip:port/應用名/資源名
1:根據ip和port確定是哪個tomcat。
2:根據應用名確定是哪個應用。
3:根據資源名來確定訪問哪個資源。
4:如果web.xml配置的DispatcherServlet的攔截路徑是“*.do/*.action”,則springmvc不會處理靜態資源的請求,靜態資源的請求最終還是交由tomcat的默認Servlet來處理。(tomcat的默認Servlet的作用:首先所有的請求進入tomcat,其次進入應用,然後開始遍歷應用中配置的Servlet的攔截路徑,如果沒有匹配到應用指定的所有servlet路徑,那麼就會流到默認的servlet。)
5:如果web.xml配置的DispatcherServlet的攔截路徑是“/”,則springmvc也會處理對靜態資源的請求,這樣就會出現問題。
問題描述:
如果在配置DispatcherServlet的時候,攔截 *.do或者*.action這樣的URL,由於不會攔截對*.jpg,*.css,*.js等靜態資源的訪問,所以靜態資源的請求最終交由Tomcat的默認Servlet來處理,就不會出現訪問不到靜態資源的問題。但是如果在配置DispatcherServlet時攔截“/”,攔截了所有的請求,即同時攔截了對*.js,*.jpg的訪問,則會出現找不到靜態資源文件,報404錯誤。
方案一:讓Tomcat的defaultServlet來處理靜態文件。(在springmvc攔截到對靜態資源的訪問之前搶先用默認Servlet攔截到對靜態資源的訪問)
<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>
要配置多個servlet-mapping,每種類型文件配置一個;要寫在DispatcherServlet的前面, 讓defaultServlet先攔截,這樣對靜態資源文件的請求就不會進入SpringMVC了。
各種web服務器默認Servlet的名字如下:
Tomcat, Jetty, JBoss, and GlassFish 默認 Servlet的名字 -- "default"
Google App Engine 默認 Servlet的名字 -- "_ah_default"
Resin 默認 Servlet的名字 -- "resin-file"
WebLogic 默認 Servlet的名字 -- "FileServlet"
默認的Servlet爲什麼能處理靜態請求呢?
方案二: 使用<mvc:resources /> (在springmvc攔截到對靜態資源的訪問之後,由springmvc對靜態資源特殊處理)
<mvc:resources/> 的使用方法:
<!--對靜態資源文件的訪問-->
<mvc:resources mapping="/images/**" location="/images/" />
在mapping屬性配置頁面文件中對靜態資源的請求路徑,在location屬性配置靜態資源存放的目錄。
mapping屬性會將符合條件的請求映射到 ResourceHttpRequestHandler 進行處理,最終從location指定的目錄中找到靜態資源,並向客戶端做出響應。
方案三 :使用<mvc:default-servlet-handler/>(在springmvc攔截到對靜態資源的訪問之後,再將靜態資源交由默認Servlet進行處理)
在Spring MVC 的配置文件中提供了一個<mvc:default-servlet-handler/>標籤。在 WEB 容器啓動的時候會在上下文中定義一個 DefaultServletHttpRequestHandler,它會對DispatcherServlet的請求進行處理(即被DispatcherServlet攔截的請求下一步會經過DefaultServletHttpRequestHandler);如果該請求已經作了映射,那麼會接着交給後臺對應的處理程序;如果沒有作映射,就交給 WEB 應用服務器默認的 Servlet 處理(即Tomcat默認的Servlet),從而找到對應的靜態資源;只有再找不到資源時纔會報錯。
和方案一中說的一樣,某些 WEB 應用服務器默認的 Servlet的名字是 default。如果默認 Servlet 用不同名稱自定義配置,或者在缺省 Servlet 名稱未知的情況下使用了不同的 Servlet 容器,則必須顯式提供默認 Servlet 的名稱,如下:
<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>
這都是在xml中配置的情況,應該還有使用JavaConfig配置的情況,待總結……