瀏覽器緩存內(nèi)幕及解決方案
- 瀏覽器緩存內(nèi)幕及解決方案
- 在下面三種不同的情況下,瀏覽器的緩存情況不同:
- 1).Servlet沒(méi)有覆蓋getLastModified方法,響應(yīng)消息中無(wú)LastModified頭字段,在瀏覽器緩存的文檔無(wú)“上次修改時(shí)間”.
- 2).有g(shù)etLastModified方法,響應(yīng)消息中有LastModified頭字段,但返回時(shí)間晚于緩存文檔“上次修改時(shí)間”
- 3).有g(shù)etLastModified方法,響應(yīng)消息中有LastModified頭字段,但返回時(shí)間早于等于緩存文檔“上次修改時(shí)間”
- 后退、前進(jìn)、轉(zhuǎn)到(手工輸入后按回車(chē)) 通過(guò)超鏈接訪問(wèn) 刷新
- 1)不發(fā)請(qǐng)求,直接使用緩存 發(fā)出請(qǐng)求 發(fā)出請(qǐng)求
- 2)不發(fā)請(qǐng)求,直接使用緩存 不發(fā)請(qǐng)求 發(fā)出請(qǐng)求,返回200
- 3)不發(fā)請(qǐng)求,直接使用緩存 不發(fā)請(qǐng)求 發(fā)出請(qǐng)求,返回304
- 2、如何禁止Servlet的緩存?(張老師JavaWeb書(shū)第236頁(yè))
- Java代碼
- response.setDateHeader("Expires", 0);
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- response.setDateHeader("Expires", 0);
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- 3、如何禁止JSP頁(yè)面的緩存?
- Html代碼
- response.setDateHeader("Expires", 0);
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- < http-equivhttp-equiv="pragma" content="no-cache">
- < http-equivhttp-equiv="cache-control" content="no-cache">
- < http-equivhttp-equiv="expires" content="0">
- response.setDateHeader("Expires", 0);
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- < http-equiv="pragma" content="no-cache">
- < http-equiv="cache-control" content="no-cache">
- < http-equiv="expires" content="0">
- 4、如何禁止靜態(tài)頁(yè)面的緩存?(張老師JavaWeb書(shū)第238頁(yè))
- Html代碼
- < http-equivhttp-equiv="pragma" content="no-cache">
- < http-equivhttp-equiv="cache-control" content="no-cache">
- < http-equivhttp-equiv="expires" content="0">
- < http-equiv="pragma" content="no-cache">
- < http-equiv="cache-control" content="no-cache">
- < http-equiv="expires" content="0">
- 靜態(tài)頁(yè)面被禁止后,刷新瀏覽器返回304
- JSP頁(yè)面被禁止后,刷新瀏覽器返回200
- web開(kāi)發(fā)中的緩存問(wèn)題的研究
- 一般情況下,瀏覽器都會(huì)緩存已經(jīng)訪問(wèn)過(guò)的頁(yè)面內(nèi)容,關(guān)于如何禁止瀏覽器緩存的介紹,在網(wǎng)上到處都有相關(guān)的文章,但是,關(guān)于瀏覽器如何利用緩存,如何處理緩存的講解,卻鮮有人談及。我一直為這個(gè)問(wèn)題所困惑,這個(gè)問(wèn)題也是絕大多數(shù)有經(jīng)驗(yàn)的WEB開(kāi)發(fā)人員所共同面臨的問(wèn)題,我有些朋友已做過(guò)幾十個(gè)大大小小的WEB項(xiàng)目,當(dāng)與他們交流這些問(wèn)題時(shí),他們雖然也在項(xiàng)目中遇到和解決過(guò)這些問(wèn)題,但由于沒(méi)有足夠的時(shí)間和精力來(lái)仔細(xì)思考這些問(wèn)題的原因和細(xì)節(jié),他們對(duì)這些問(wèn)題始終也是一知半解、含糊不清,而目前又很少關(guān)于這些問(wèn)題的專(zhuān)門(mén)和詳細(xì)講解,我最近用了兩天的時(shí)間,把瀏覽器緩存的問(wèn)題透徹地研究了一翻,主要包括一下方面的細(xì)節(jié)。
- 1 如何禁止瀏覽器緩存,這是最簡(jiǎn)單的問(wèn)題,本來(lái)羞于在此講解,但是為了完整性,不妨將其列為一個(gè)知識(shí)點(diǎn)。
- 2 瀏覽器在訪問(wèn)已緩存過(guò)的資源時(shí),它在什么情況下會(huì)向服務(wù)器發(fā)送請(qǐng)求?在什么情況下根本就不向服務(wù)器發(fā)送請(qǐng)求。這與瀏覽器的緩存設(shè)置有關(guān)!但是,由于幾乎所有人的瀏覽器都是采用的默認(rèn)設(shè)置,所以,重點(diǎn)應(yīng)該放在分析瀏覽器的默認(rèn)緩存設(shè)置的研究上。
- 3 當(dāng)通過(guò)其他網(wǎng)頁(yè)文檔中的超鏈接來(lái)訪問(wèn)某一個(gè)已經(jīng)緩存過(guò)的資源時(shí),瀏覽器是否要向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求?如果不發(fā),則會(huì)出現(xiàn)一個(gè)問(wèn)題:當(dāng)銷(xiāo)售一件商品后再回到商品庫(kù)存的顯示頁(yè)面時(shí),看到的還將是先前看到的內(nèi)容,而不是更新的庫(kù)存數(shù)據(jù)。但是,在訪問(wèn)一個(gè)普通的HTML文件時(shí),如果瀏覽器每次都向服務(wù)器發(fā)送訪問(wèn)請(qǐng)求,效率就會(huì)相對(duì)低下,這就失去了緩存的意義和價(jià)值。所以,結(jié)論應(yīng)是瀏覽器訪問(wèn)動(dòng)態(tài)頁(yè)面時(shí)不能使用緩存,而訪問(wèn)靜態(tài)頁(yè)面時(shí)應(yīng)該使用緩存,但是,僅僅根據(jù)被訪問(wèn)頁(yè)面的資源名稱(chēng),瀏覽器是無(wú)法知道商品庫(kù)存的顯示頁(yè)面是屬于動(dòng)態(tài)內(nèi)容,還是屬于靜態(tài)內(nèi)容。瀏覽器是根據(jù)什么方式來(lái)判斷它緩存的資源是動(dòng)態(tài)的,還是靜態(tài)的呢?在什么請(qǐng)求下,它會(huì)對(duì)緩存的資源總是發(fā)出新的請(qǐng)求呢?
- 4。對(duì)于緩存的內(nèi)容,即使瀏覽器向服務(wù)器發(fā)送了請(qǐng)求,但服務(wù)器在接收到請(qǐng)求后,可能不會(huì)返回內(nèi)容,而是讓瀏覽器繼續(xù)使用緩存的內(nèi)容,這在實(shí)際應(yīng)用中有什么好處呢?如何處理其具體細(xì)節(jié)呢?
- 5。服務(wù)器端也有緩存,當(dāng)服務(wù)器接收到瀏覽器的請(qǐng)求后,假設(shè)它返回響應(yīng)內(nèi)容,但返回的響應(yīng)內(nèi)容可能不是最新的內(nèi)容,而很可能是一個(gè)舊的緩存版本,這又是怎么回事呢?
- 瀏覽器緩存內(nèi)幕與getLastModified方法
- 在HttpServlet類(lèi)中定義了一個(gè)getLastModified方法,其完整語(yǔ)法定義如下:
- protected long getLastModified(HttpServletRequest req)
- 其中的返回值表示自1970年1月1日的0點(diǎn)0分0秒開(kāi)始計(jì)算的一個(gè)毫秒數(shù),HttpServlet類(lèi)中定義的getLastModified方法總是返回一個(gè)負(fù)數(shù),在HttpServlet子類(lèi)中可以對(duì)這個(gè)方法進(jìn)行覆蓋,以便返回一個(gè)代表當(dāng)前輸出的響應(yīng)內(nèi)容的修改時(shí)間,HttpServlet類(lèi)的service方法可以根據(jù)這個(gè)返回值在響應(yīng)消息中自動(dòng)生成Last-Modified頭字段。
- 一般情況下,瀏覽器都會(huì)緩存已經(jīng)訪問(wèn)過(guò)的頁(yè)面內(nèi)容,getLastModified方法的返回值可以影響瀏覽器如何處理和利用緩存內(nèi)容。在詳細(xì)了解getLastModified方法的應(yīng)用之前,應(yīng)該先對(duì)瀏覽器的緩存機(jī)制有所了解。
- 單擊IE瀏覽器的“工具“Internet選項(xiàng)”菜單,打開(kāi)“Internet選項(xiàng)”對(duì)話框,接著再單擊“常規(guī)”選項(xiàng)卡中的“Internet臨時(shí)文件”欄中的“設(shè)置”按鈕,打開(kāi)“設(shè)置”對(duì)話框。“設(shè)置”對(duì)話框的“Internet臨時(shí)文件夾”欄中,可以看到瀏覽器保存所有緩存頁(yè)面內(nèi)容的文件夾的完整目錄名稱(chēng)。
- “每次訪問(wèn)此頁(yè)時(shí)檢查”選項(xiàng)表示瀏覽器每次訪問(wèn)一個(gè)頁(yè)面時(shí),不管瀏覽器是否緩存過(guò)此頁(yè)面,都要向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求。這種設(shè)置的優(yōu)點(diǎn)是實(shí)時(shí)性很強(qiáng),肯定能夠訪問(wèn)到網(wǎng)頁(yè)的最新內(nèi)容,但是如果網(wǎng)頁(yè)內(nèi)容很少更新,這種設(shè)置的訪問(wèn)效率就比較低了。
- “每次啟動(dòng)Internet Explorer時(shí)檢查”選項(xiàng)表示在瀏覽器的每次啟動(dòng)運(yùn)行期間,在第一次訪問(wèn)一個(gè)頁(yè)面時(shí),不管瀏覽器是否緩存過(guò)此頁(yè)面,都要向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,但是在瀏覽器的本次啟動(dòng)運(yùn)行期間對(duì)該頁(yè)面的后續(xù)訪問(wèn),瀏覽器將不再向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,而是直接使用緩存中的內(nèi)容。這種設(shè)置具有較高的訪問(wèn)效率,同時(shí)也兼顧了較好的實(shí)時(shí)性,它可以保證每次啟動(dòng)瀏覽器后看到的都是最新的網(wǎng)頁(yè)內(nèi)容。
- “自動(dòng)”選項(xiàng)與“每次啟動(dòng)Internet Explorer時(shí)檢查”選項(xiàng)的功能相似,只是對(duì)圖像的訪問(wèn)有所不同,如果隨著時(shí)間的推移,瀏覽器發(fā)現(xiàn)網(wǎng)頁(yè)上的圖像更新并不頻繁,這樣,即使瀏覽器在對(duì)某個(gè)已緩存的圖像執(zhí)行本次啟動(dòng)運(yùn)行以來(lái)的第一次訪問(wèn)時(shí),它也不一定會(huì)向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,而是干脆直接使用緩存中的內(nèi)容。“自動(dòng)”選項(xiàng)是瀏覽器的默認(rèn)設(shè)置,所以,幾乎所有人的瀏覽器都是按照這種方式工作的,這個(gè)選項(xiàng)的作用和意義應(yīng)該成為讀者熟悉的重點(diǎn)。
- “不檢查”選項(xiàng)表示瀏覽器不管在什么情況下訪問(wèn)一個(gè)頁(yè)面時(shí),只要能夠在本地找到此頁(yè)面的緩存信息,瀏覽器就不會(huì)向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,而是直接使用緩存的內(nèi)容。這種設(shè)置的優(yōu)點(diǎn)是訪問(wèn)效率很高,但是如果服務(wù)器端的網(wǎng)頁(yè)內(nèi)容更新后,瀏覽器看到的內(nèi)容很可能是過(guò)期的內(nèi)容。
- 在瀏覽器的“檢查所存網(wǎng)頁(yè)的較新版本”的功能項(xiàng)采用默認(rèn)的“自動(dòng)”設(shè)置項(xiàng)的情況下,如果瀏覽器剛剛訪問(wèn)過(guò)一個(gè)網(wǎng)頁(yè),服務(wù)器端就更新了這個(gè)網(wǎng)頁(yè)的內(nèi)容,當(dāng)瀏覽在關(guān)閉前又重新訪問(wèn)這個(gè)頁(yè)面時(shí),用戶(hù)看到的將不是更新的網(wǎng)頁(yè)內(nèi)容,而是過(guò)期的網(wǎng)頁(yè)內(nèi)容。為了提高瀏覽效率,在訪問(wèn)靜態(tài)的網(wǎng)頁(yè)內(nèi)容時(shí),這么一點(diǎn)小概率的過(guò)期信息還是應(yīng)該允許的,并且這些過(guò)期信息也不會(huì)造成什么不好的后果,就像你偶爾有一次看到了前一天發(fā)生的新聞,而不是當(dāng)天的新聞,這又有什么問(wèn)題呢?可是,如果瀏覽器訪問(wèn)的是一個(gè)動(dòng)態(tài)網(wǎng)頁(yè),這本來(lái)就要求瀏覽器在其整個(gè)運(yùn)行期間的每次訪問(wèn)都能看到最新的內(nèi)容,例如,銷(xiāo)售一件商品后再回到商品庫(kù)存的顯示頁(yè)面時(shí),看到的就應(yīng)該是更新的庫(kù)存數(shù)據(jù),而不應(yīng)該是先前看到的內(nèi)容。僅僅根據(jù)被訪問(wèn)頁(yè)面的資源名稱(chēng),瀏覽器是無(wú)法知道商品庫(kù)存的顯示頁(yè)面是屬于動(dòng)態(tài)內(nèi)容,還是屬于靜態(tài)內(nèi)容。對(duì)于這種情況,瀏覽器將根據(jù)響應(yīng)消息中是否包含Last-Modified頭字段來(lái)進(jìn)行處理,如果響應(yīng)消息中沒(méi)有包含Last- Modified頭字段,它將在每次訪問(wèn)此頁(yè)面時(shí)都向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,否則,它僅在每次啟動(dòng)運(yùn)行后的第一次訪問(wèn)此頁(yè)面時(shí)才向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求,而在啟動(dòng)運(yùn)行期間對(duì)此頁(yè)面的后續(xù)訪問(wèn)都不再向服務(wù)器發(fā)出訪問(wèn)請(qǐng)求。
- 響應(yīng)消息中的Last-Modified頭字段可用于指定響應(yīng)內(nèi)容的最后更新時(shí)間,當(dāng)客戶(hù)機(jī)緩存此文檔內(nèi)容后,它在以后的請(qǐng)求消息中將根據(jù) Last-Modified頭字段指定的時(shí)間來(lái)生成If-Modified-Since請(qǐng)求頭字段,以指出緩存文檔的最后更新時(shí)間。只有文檔的修改時(shí)間比 If-Modified-Since請(qǐng)求頭指定的時(shí)間新時(shí),服務(wù)器才會(huì)返回文檔內(nèi)容。如果自從If-Modified-Since指定的時(shí)間以來(lái),網(wǎng)頁(yè)內(nèi)容沒(méi)有發(fā)生修改,服務(wù)器將返回一個(gè)304(Not Modified)狀態(tài)碼來(lái)表示瀏覽器緩存的版本是最新的,而不會(huì)向?yàn)g覽器返回文檔內(nèi)容,瀏覽器則繼續(xù)使用以前緩存的內(nèi)容。通過(guò)這種方式,可以在一定程度上減少瀏覽器與服務(wù)器之間的通信數(shù)據(jù)量,從而提高了通信效率。
- HttpServlet類(lèi)為If-Modified-Since請(qǐng)求頭和Last-Modified頭字段的這種應(yīng)用提供了處理機(jī)制,當(dāng)繼承了 HttpServlet類(lèi)的Servlet程序接收到一個(gè)GET方式的訪問(wèn)請(qǐng)求時(shí),HttpServlet中重載的service方法在調(diào)用doGet方法之前,它還將調(diào)用getLastModified方法,并根據(jù)getLastModified方法的返回值來(lái)決定是否調(diào)用doGet方法和在響應(yīng)消息中是否生成Last-Modified頭字段,具體規(guī)則如下:
- 當(dāng)getLastModified方法返回一個(gè)負(fù)數(shù)時(shí),不管請(qǐng)求消息中的情況怎樣,service方法都將直接調(diào)用doGet方法來(lái)生成響應(yīng)內(nèi)容,這正是HTTPServlet類(lèi)中定義的getLastModified方法的行為;
- 當(dāng)getLastModified方法返回一個(gè)正數(shù),且請(qǐng)求消息中沒(méi)有包含If-Modified-Since請(qǐng)求頭時(shí)(這往往出現(xiàn)在第對(duì)某個(gè)資源的第一次訪問(wèn)時(shí)),或者請(qǐng)求消息中包含的If-Modified-Since請(qǐng)求頭中的時(shí)間值比getLastModified方法返回的時(shí)間值舊時(shí),service方法將根據(jù)getLastModified方法的返回值生成一個(gè)Last-Modified頭字段,然后調(diào)用doGet方法生成響應(yīng)內(nèi)容;
- 當(dāng)getLastModified方法返回一個(gè)正數(shù)時(shí),且請(qǐng)求消息中包含的If-Modified-Since請(qǐng)求頭中的時(shí)間值比 getLastModified方法返回的時(shí)間值新或者與之相同時(shí),service方法將不調(diào)用doGet方法,而是向?yàn)g覽器返回一個(gè)304(Not Modified)狀態(tài)碼表示瀏覽器可以使用其以前緩存的內(nèi)容。
===================================================================================================
使用Filter配置禁止緩存功能
Java代碼
NoCacheFilter.class
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class NoCacheFilter implements Filter {
public void destroy() {
}
//瀏覽器不緩存頁(yè)面
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException{
//設(shè)置禁止緩存的消息頭
((HttpServletResponse)response).setHeader("Pragma","No-cache");
((HttpServletResponse)response).setHeader("Cache-Control","no-cache");
((HttpServletResponse)response).setHeader("Expires","0");//禁止緩存
chain.doFilter(request, response);
System.out.print("NoCacheFilter");
}
public void init(FilterConfig arg0) throws ServletException {
}
}web.xml配置
NoCacheFilter.class
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class NoCacheFilter implements Filter {
public void destroy() {
}
//瀏覽器不緩存頁(yè)面
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException{
//設(shè)置禁止緩存的消息頭
((HttpServletResponse)response).setHeader("Pragma","No-cache");
((HttpServletResponse)response).setHeader("Cache-Control","no-cache");
((HttpServletResponse)response).setHeader("Expires","0");//禁止緩存
chain.doFilter(request, response);
System.out.print("NoCacheFilter");
}
public void init(FilterConfig arg0) throws ServletException {
}
}
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>com.huadi.tools.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<filter-class>com.huadi.tools.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/servlet/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
posted on 2012-09-07 17:27 魯勝迪 閱讀(2620) 評(píng)論(0) 編輯 收藏