Java互聯網架構-風花雪月談寫Tomcat容器動靜態資源響應

概述

Tomcat 伺服器是一個免費的開放源代碼的Web 應用伺服器,是Apache 軟體基金會(Apache Software Foundation)的Jakarta 項目中的一個核心項目,由Apache、Sun 和其他一些公司及個人共同開發而成。由於有了Sun 的參與和支持,最新的Servlet 和JSP 規範總是能在Tomcat 中得到體現,Tomcat 5 支持最新的Servlet 2.4 和JSP 2.0 規範。因為Tomcat 技術先進、性能穩定,而且免費,因而深受Java 愛好者的喜愛並得到了部分軟體開發商的認可,成為目前比較流行的Web 應用伺服器。目前最新版本是8.0。

1.激活Tomcat的DefaultServlet來處理靜態文件

Advertisements

一定要說明: 我測試如果在項目的web.xml配置是無法啟動作用的,需要在全局的tomcat->conf->web.xml中激活處理靜態文件的方式

<!-- 方式一:激活Tomcat的defaultServlet來處理靜態文件 開始 -->

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>*.ico</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>default</servlet-name>

Advertisements

<url-pattern>/static/*</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>/resources/*</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>/upload/*</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>*.png</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>

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>*.css</url-pattern>

</servlet-mapping>

<!-- 結束,一定要配置 / 的前面 -->

<!-- 原來的路徑 -->

<servlet-mapping>

<servlet-name>default</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

2.使用<mvc:default-servlet-handler/>

在springMVC-servlet.xml中配置<mvc:default-servlet-handler />后,會在Spring MVC上下文中定義一個org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它會像一個檢查員,對進入DispatcherServlet的URL進行篩查,如果發現是靜態資源的請求,就將該請求轉由Web應用伺服器默認的Servlet處理,如果不是靜態資源的請求,才由DispatcherServlet繼續處理。

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

default-servlet-name在不同容器中的名字

Tomcat, Jetty, JBoss, and GlassFish 自帶的默認Servlet的名字 -- "default"

Google App Engine 自帶的 默認Servlet的名字 -- "_ah_default"

Resin 自帶的 默認Servlet的名字 -- "resin-file"

WebLogic 自帶的 默認Servlet的名字 -- "FileServlet"

WebSphere 自帶的 默認Servlet的名字 -- "SimpleFileServlet"

3.在spring3.0.4以後版本提供了<mvc:resources>

<mvc:default-servlet-handler />將靜態資源的處理經由Spring MVC框架交回Web應用伺服器處理。而<mvc:resources />更進一步,由Spring MVC框架自己處理靜態資源,並添加一些有用的附加值功能。

->需要仔細讀一下

首先,<mvc:resources />允許靜態資源放在任何地方,如WEB-INF目錄下、類路徑下等,你甚至可以將JavaScript等靜態文件打到JAR包中。通過location屬性指定靜態資源的位置,由於location屬性是Resources類型,因此可以使用諸如"classpath:"等的資源前綴指定資源位置。傳統Web容器的靜態資源只能放在Web容器的根路徑下,<mvc:resources />完全打破了這個限制。

其次,<mvc:resources />依據當前著名的Page Speed、YSlow等瀏覽器優化原則對靜態資源提供優化。你可以通過cacheSeconds屬性指定靜態資源在瀏覽器端的緩存時間,一般可將該時間設置為一年,以充分利用瀏覽器端的緩存。在輸出靜態資源時,會根據配置設置好響應報文頭的Expires 和 Cache-Control值。

在接收到靜態資源的獲取請求時,會檢查請求頭的Last-Modified值,如果靜態資源沒有發生變化,則直接返回303相應狀態碼,提示客戶端使用瀏覽器緩存的數據,而非將靜態資源的內容輸出到客戶端,以充分節省帶寬,提高程序性能。

示例代碼

<mvc:resources location="/,classpath:/META-INF/publicResources/" mapping="/resources/**"/>

以上配置將Web根路徑"/"及類路徑下 /META-INF/publicResources/ 的目錄映射為/resources路徑。假設Web根路徑下擁有images、js這兩個資源目錄,在images下面有bg.gif圖片,在js下面有test.js文件,則可以通過 /resources/images/bg.gif 和 /resources/js/test.js 訪問這二個靜態資源。

假設WebContent還擁有images/bg1.gif 及 js/test1.js,則也可以在網頁中通過 /resources/images/bg1.gif 及 /resources/js/test1.js 進行引用。

或者 我的習慣

<!-- 靜態資源映射,如果有多個目錄使用逗號進行分割 -->

<mvc:resources location="/WEB-INF/static/images/,/WEB-INF/static/img/" mapping="/image/**" ></mvc:resources>

<mvc:resources location="/WEB-INF/static/css/" mapping="/css/**" ></mvc:resources>

<mvc:resources location="/WEB-INF/static/js/" mapping="/js/**" ></mvc:resources>

mapping:映射

cache-period:可以指定靜態資源在瀏覽器端的緩存時間,這裡設置是一年,springmvc在輸出響應流時,會設置好響應頭部的Expries還有Cache-Control的值

location:Spring Resource類型,可以讀取任意位置的靜態資源,報錯jar中的靜態資源,使用」classpath:」的靜態資源,還有WEB-INF目錄下的靜態資源等等。

兩個*,它表示映射resources/下所有的URL,包括子路徑(即接多個/)

映射到ResourceHttpRequestHandler進行處理 location指定靜態資源的位置.可以是web application根目錄下、jar包裡面,這樣可以把靜態資源壓縮到jar包中 cache-period 可以使得靜態資源進行web cache

異常

如果出現下面的錯誤,可能是沒有配置<mvc:annotation-driven />的原因。

報錯WARNING: No mapping found for HTTP request with URI [/shxt/image/0.icon] in DispatcherServlet with name 'springMVC'

使用<mvc:resources/>元素,把mapping的URI註冊到SimpleUrlHandlerMapping的urlMap中,key為mapping的URI pattern值,而value為ResourceHttpRequestHandler,這樣就巧妙的把對靜態資源的訪問由HandlerMapping轉到ResourceHttpRequestHandler處理並返回,所以就支持classpath目錄,jar包內靜態資源的訪問.另外需要注意的一點是,不要對SimpleUrlHandlerMapping設置defaultHandler.因為對static uri的defaultHandler就是ResourceHttpRequestHandler,否則無法處理static resources request.

推薦配置如下

<mvc:resources mapping="/resources/**" cache-period="3000" location="/resources/" order="0">

<mvc:resource-chain resource-cache="true">

<mvc:resolvers>

<bean class="org.springframework.web.servlet.resource.GzipResourceResolver"/>

</mvc:resolvers>

</mvc:resource-chain>

</mvc:resources>

<mvc:resources mapping="/static/**" cache-period="30" location="/static/" order="0"/>

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

因為我這裡的靜態文件都在resources和static目錄下,所以這裡只配置了這兩個路徑。後面的location最後一定要有一個/結束,否則靜態資源是訪問不到的,order參數是Spring配置的優先順序,數字越小越優先。cache-period是緩存的秒數,這裡將resources的緩存設置為3000秒,也就是50分鐘,static的是30秒。然後在resources裡面配置了GzipResourceResolver,是用來嘗試返回GZIP的文件,如果有則返回,沒有就返回原文件。像是比較大的JS文件就應該使用GZIP壓縮后的文件返回,可以大大的減小下載的時間。

放在後面的話

最後再說明一下,方案二、方案三 在訪問靜態資源時,如果有匹配的(近似)總攔截器,就會走攔截器。如果你在攔截中實現許可權檢查,要注意過濾這些對靜態文件的請求。

靜態資源版本控制解決方案-加入版本號碼

/**

* 資源版本控制器

*/

public class ResVersionExposer implements ServletContextAware {

private ServletContext servletContext ;

private String resPath ;

@Override

public void setServletContext(ServletContext servletContext) {

this.servletContext = servletContext;

}

public void init(){

String version = "1.2.1" ; //可以把版本號配置在application.properties

resPath = "resource/" + version + "/";

servletContext.setAttribute("resPath", resPath);

}

public String getResPath() {

return resPath;

}

}

然後我們在配置文件中配置靜態文件的路徑

<bean id="rve" init-method="init" class="com.hanpang.util.resource.ResVersionExposer" />

<mvc:resources location="/content/" cache-period="31556926" mapping="${rve.resPath}" />

jsp頁面就這樣子請求靜態資源文件

<link rel="stylesheet" type="text/css"

href="${resPath}/css/catalog/catalogEdit.css" />

總結

到這裡,風花雪月談寫Tomcat容器動靜態資源響應就結束了,,不足之處還望大家多多包涵!!覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持。(吹一波,233~~)

下面和大家交流幾點編程的經驗:

1、多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

2丶 測試、測試再測試,如果你不徹底測試自己的代碼,那恐怕你開發的就不只是代碼,可能還會聲名狼藉。

3丶 簡化編程,加快速度,代碼風騷,在你完成編碼后,應回頭並且優化它。從長遠來看,這裡或那裡一些的改進,會讓後來的支持人員更加輕鬆。

最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步。

內部交流群569068099 歡迎各位前來交流和分享, 驗證:(007)

Java小毛驢,頭條出品,每天一篇乾貨,喜歡就收藏+關注

Advertisements

你可能會喜歡