<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    http://www.jdon.com/40381


    Last-Modified和Expires針對(duì)瀏覽器,而ETag則與客戶端無(wú)關(guān),所以可適合REST架構(gòu)中。兩者都應(yīng)用在瀏覽器端的區(qū)別是:Expires日期到達(dá)前,瀏覽器不會(huì)再發(fā)出新的請(qǐng)求,除非用戶按瀏覽器的刷新,所以,Last-Modified和Expires基本是降低瀏覽器向服務(wù)器發(fā)出請(qǐng)求的次數(shù),而ETag更側(cè)重客戶端和服務(wù)器之間聯(lián)系。

    先談Last-Modified和Expires,最新的Tomcat 7 將ExpireFilter加入其容器中,這樣,Java WEB也可以象Apache的Mod_expire模塊一樣對(duì)Http頭部進(jìn)行統(tǒng)一設(shè)置了,不過(guò)它只對(duì)響應(yīng)文檔類(lèi)型進(jìn)行統(tǒng)一設(shè)置判斷,如text/html或text/image 或/css等等,如果想對(duì)個(gè)別URL輸出的jsp進(jìn)行定制就不行,urlrewrite據(jù)說(shuō)是可以,但是要把URL在其配置文件再配置一下,麻煩,一旦jsp改動(dòng)影響面大,還有一個(gè)問(wèn)題就是web.xml配置了Tomcat 7容器的ExpireFilter,與容器耦合,移植性差(移植到Resin就不行了)。

    所以,我在JiveJdon 4.2最新版本中,通過(guò)加入下面一段代碼在服務(wù)器端對(duì)來(lái)自客戶端的Last-Modified以及當(dāng)前時(shí)間進(jìn)行判斷,如未過(guò)期,response.setStatus設(shè)為304,可以終止后面的各種Jsp界面計(jì)算,直接返回瀏覽器一個(gè)304的響應(yīng)包,JSP頁(yè)面也不會(huì)輸出到客戶端,將帶寬節(jié)省給更加需要互動(dòng)實(shí)時(shí)性的請(qǐng)求。

    再談?wù)凟Tag,ETag定義:RFC2616(也就是HTTP/1.1)中沒(méi)有說(shuō)明ETag該是什么格式的,只要確保用雙引號(hào)括起來(lái)就行了,所以你可以用文件的hash,甚至是直接用Last-Modified,以下是服務(wù)器端返回的格式:
    ETag: "50b1c1d4f775c61:df3" 客戶端向服務(wù)端發(fā)出的請(qǐng)求:If-None-Match: W/"50b1c1d4f775c61:df3" 這樣,在J2EE/JavaEE服務(wù)器端,我們判斷如果ETag沒(méi)改變也是返回狀態(tài)304,起到類(lèi)似Last-Modified和Expires效果。

    與Last-Modified和Expires區(qū)別是:如果過(guò)了Expires日期,服務(wù)器肯定會(huì)再次發(fā)出JSP完整響應(yīng);或者用戶強(qiáng)按瀏覽器的刷新按鈕,服務(wù)器也必須響應(yīng),apache等靜態(tài)頁(yè)面輸出也是這樣,但是這時(shí)動(dòng)態(tài)頁(yè)面就發(fā)揮了作用,如果JSP涉及的業(yè)務(wù)領(lǐng)域模型還是沒(méi)有更新,和原來(lái)一樣,那么就不必再將動(dòng)態(tài)頁(yè)面輸出了(瀏覽器客戶端已有一份),從Etag中獲取上次設(shè)置的領(lǐng)域模型對(duì)象修改日期,和現(xiàn)在內(nèi)存中領(lǐng)域模型(In-memory Model)修改日期進(jìn)行比較,如果修改日期一致,表示領(lǐng)域模型沒(méi)有被更新過(guò),那么返回響應(yīng)包304,瀏覽器將繼續(xù)用本地緩存的該頁(yè)面,再次節(jié)省了帶寬傳輸。

    通過(guò)上述Expire和Etag兩次緩存,可以大大降低服務(wù)器的響應(yīng)負(fù)載,如果你的應(yīng)用不是狀態(tài)集中并發(fā)修改和實(shí)時(shí)輸出,而是分散修改然后分發(fā),如個(gè)人空間 個(gè)人博客(每個(gè)人只是修改它們自己的狀態(tài),不影響全局)或QQ類(lèi)似個(gè)人工具,那么采取這樣的方法效果非常明顯,實(shí)際就是一種動(dòng)態(tài)頁(yè)面靜態(tài)化技術(shù),但比通常事先進(jìn)行頁(yè)面靜態(tài)化要靈活強(qiáng)大。

    InfoQ的那篇:http://www.infoq.com/articles/etags還用MD5計(jì)算放入其中,Md5計(jì)算稍微復(fù)雜點(diǎn),負(fù)載大了點(diǎn),有的人結(jié)合Hibernate或數(shù)據(jù)庫(kù)觸發(fā)器來(lái)判斷數(shù)據(jù)庫(kù)數(shù)據(jù)是否更新,以決定Etag的更新,這將表現(xiàn)層和持久層耦合在一起,由于JiveJdon采取的是MDD/DDD模型驅(qū)動(dòng)架構(gòu),表現(xiàn)層的Etag更新是根據(jù)中間業(yè)務(wù)層的模型對(duì)象修改日期來(lái)決定,不涉及數(shù)據(jù)庫(kù)層,而且起到服務(wù)器緩存的更新和http的Etag更新一致的效果,在松耦合設(shè)計(jì)和性能上取得綜合平衡。

    代碼如下:

    public static boolean checkHeaderCache(long adddays, long modelLastModifiedDate, HttpServletRequest request, HttpServletResponse response) {
    // com.jdon.jivejdon.presentation.filter.ExpiresFilter
    request.setAttribute(
    "myExpire", adddays);

    // convert seconds to ms.
    long adddaysM = adddays * 1000;
    long header = request.getDateHeader(
    "If-Modified-Since");
    long now = System.currentTimeMillis();
    if (header > 0 && adddaysM > 0) {
    if (modelLastModifiedDate > header) {
    // adddays = 0; // reset
    response.setStatus(HttpServletResponse.SC_OK);
    return true;
    }
    if (header + adddaysM > now) {
    // during the period happend modified
    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
    return false;
    }
    }

    // if over expire data, see the Etags;
    // ETags if ETags no any modified
    String previousToken = request.getHeader(
    "If-None-Match");
    if (previousToken != null && previousToken.equals(Long.toString(modelLastModifiedDate))) {
    // not modified
    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
    return false;
    }
    // if th model has modified , setup the new modified date
    response.setHeader(
    "ETag", Long.toString(modelLastModifiedDate));
    setRespHeaderCache(adddays, request, response);
    return true;

    }

    public static boolean setRespHeaderCache(long adddays, HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute(
    "myExpire", adddays);

    long adddaysM = adddays * 1000;
    String maxAgeDirective =
    "max-age=" + adddays;
    response.setHeader(
    "Cache-Control", maxAgeDirective);
    response.setStatus(HttpServletResponse.SC_OK);
    response.addDateHeader(
    "Last-Modified", System.currentTimeMillis());
    response.addDateHeader(
    "Expires", System.currentTimeMillis() + adddaysM);
    return true;
    }


    posted on 2013-09-26 17:35 SIMONE 閱讀(1844) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): JSP
    主站蜘蛛池模板: 亚洲色爱图小说专区| 久久丫精品国产亚洲av| 亚洲精品国产V片在线观看| 久久夜色精品国产嚕嚕亚洲av| 久久久久亚洲av毛片大| 亚洲专区中文字幕| 男女啪啪免费体验区| 日本免费人成网ww555在线| 日本久久久免费高清| 久久国产亚洲精品无码| 8x8x华人永久免费视频| 中国亚洲女人69内射少妇| 亚洲精品无播放器在线播放| 久久狠狠躁免费观看| 亚洲最大福利视频网站| 日本XXX黄区免费看| 亚洲国产综合精品中文第一区| 四虎成人精品国产永久免费无码| 午夜福利不卡片在线播放免费| 亚洲一级片在线观看| 免费看片免费播放| 亚洲香蕉在线观看| 日本zzzzwww大片免费| 亚洲AV永久无码精品成人| 中文字幕视频免费| 亚洲欧美日韩综合久久久| 美女视频黄的全免费视频网站| 亚洲日产乱码一二三区别| 亚洲性日韩精品国产一区二区| 亚洲AV无码之国产精品| 在线a人片天堂免费观看高清| 亚洲国产福利精品一区二区| 97青青草原国产免费观看| 亚洲AV无码乱码在线观看裸奔| 97热久久免费频精品99| 亚洲香蕉久久一区二区 | 理论秋霞在线看免费| 日本一道在线日本一道高清不卡免费 | 免费能直接在线观看黄的视频 | 99在线免费观看视频| 亚洲男同gay片|