您現在的位置是:電腦技術吧?>? 編程技術 ??>??緩存,什么是緩存??>??正文詳情

緩存,什么是緩存

毓悠雅2019-12-10 16:02:45 人圍觀
簡介ie清理緩存內容緩存是web應用程序中最常用的優化技術之一。例如,我們可以使用自定義JSP標記來命名它,并封裝需要緩存的每個頁面片段。任何自定義標記都可以控制它包含的部分(緩

內容緩存是Web應用中最普通的優化技術之一,例如,可以使用一個自定義地JSP標簽我們將之命名為將每一個需要被緩存的頁面片段封裝起來。

任何自定義標簽可以控制它所包含部分 (也即預先封裝的頁面片段)在何時執行,并且動態輸出結果可以被捕獲。

標簽使得JSP容器(例如Tomcat)只生成內容一次,作為應用程序范圍內的JSP變量,來存儲每一個緩存片段。

每次JSP頁面被執行時,自定義標簽將緩存頁面片段載入而無需再次執行JSP代碼來生成輸出結果。

作為Jakarta工程的一個部分,標簽庫的開發使用了這項技術。

當被緩存內容無需被每一個用戶或者請求所定制的時候,它工作的十分良好。

  這篇文章對上面描述的技術做了改進,通過使用JSP 2.0表達式語言(EL),允許JSP頁面為每一個請求和用戶定制緩存內容。

緩存頁面片段可以包含未被JSP容器賦值的JSP表達式,在每一次頁面被執行時,由自定義標簽來確定這些表達式的值。

因此,動態內容的建立被最優化,但是緩存片段可以含有部分由每一個請求使用本機JSP表達式語言產生的內容。

通過JSP 2.0 EL API的幫助,Java開發者可以用表達式語言來使之成為可能。

  內容緩存VS數據緩存  內容緩存不是唯一的選擇。

例如, 從數據庫中提取的數據同樣可以被緩存。

事實上,由于存儲的信息中不包含HTML markup,以及要求較少的內存,數據緩存可能更加高效率。

然而在很多情況下,內存緩存更容易實現。

假設在某個案例總,一個應用由大量事務對象,占用重要的CPU資源,產生復雜的數據,并且用JSP頁面來呈現這些數據。

工作一切良好,直到某天突然地服務器的負載增加,需要一個緊急解決方案。

這時在事務對象和呈現表達層之間建立一個緩存層,時一個非常不錯和有效的方案。

但是必須非常快速和流暢地修改緩存動態內容的JSP頁面。

相對于簡單的JSP頁面編輯,應用程序的業務邏輯變化通常要求更多的工作量和測試;另外,如果一個頁面從多個復合源聚合信息時,Web層僅有少量的改變。

問題在于,當緩存信息變得失去時效時,緩存空間需要被釋放,而事務對象應該知道何時發生這種情況。

然而,選擇實現內容緩存還是數據緩存,或者其他的優化技術,有很多不得不考慮的因素,有時是所開發的程序所特殊要求的。

    數據緩存和內容緩存沒有必要互相排斥,它們可以一起使用。

例如,在數據庫驅動的應用中;從數據庫中提取出來的數據,和呈現該數據的HTML分別被緩存起來。

這與使用JSP實時生成的模板有些相似。

這篇文章中討論的基于EL API技術說明如何使用JSP EL來將數據載入到呈現模板中。

  使用JSP變量緩存動態內容  每當實現一個緩存機制是,都需要一個存儲緩存對象的方法,在這篇文章中涉及的是String類型的對象。

一種選擇是使用一個對象緩存框架結構,或者使用Java maps來實現自定義的緩存方案。

JSP已經擁有了稱為scoped attributes或JSP variables來提供IDobject映射,這正是緩存機制所需要的。

對于使用page或者request scope,這是沒有意義的,而在應用范圍內,這是一個很好的存儲緩存內容的位置, 因為它被所有的用戶和頁面共享。

當每一個用戶需要單獨緩存時,Session scope也可以被使用,但這不是很有效率。

JSTL標簽庫可以被是與那個來緩存內容,通過使用JSP變量正如下例所示:        ...    緩存頁面片段用下列語句輸出結果:  ${applicationScope.cachedFragment}  當緩存片段需要被每一個請求所定制的時候,到底發生了什么?  例如,如果希望包含一個計數器,需要緩存兩個片段:              ...      ...    可以使用下面語句輸出緩存內容:  ${cachedFragment1} ${counter} ${cachedFragment2} 通過專門的標簽庫的幫助,需要定制的頁面片段的緩存變得異常容易了。

上面已經提及,緩存內容可以被開始標簽()和結尾標簽()封裝起來。

而每一個定制可以使用另一個標簽()輸出一個JSP表達式(${...})來表現。

動態內容用JSP表達式緩存并在每一次緩存內容被輸出時賦值。

在下面的部分可以看到這是如何實現的。

Counter.jsp緩存了一個包含計數器的頁面片段,當每一次用戶刷新這個頁面的時候計數器會自動 1。

          JSP 變量易于使用,對于簡單的Web apps,這是一個不錯的內容緩存方案。

然而,如果應用程序產生大量的動態內容,沒有對緩存大小的控制無疑是一個問題。

一種專用的緩存框架結構能夠提供一個更加有力的方案,允許對緩存的監視,限制緩存大小,控制緩存策略,等等使用JSP 2.0表達式語言APIJSP容器(例如Tomcat)對應用EL API的JSP頁面中的表達式予以賦值,并且可以被Java代碼所使用。

這允許在Web頁面外應用JSP EL作開發,例如,對XML文件、基于文本的資源以及自定義腳本。

當需要控制何時對Web頁面中的表達式進行賦值或者書寫與之相關的表達式時,EL API同樣是有用的。

例如,緩存頁面片段可以包含自定義JSP表達式,并且當每一次緩存內容被輸出時,EL API將用來給這些表達式賦值或者重新賦值。

文章提供了一個例子程序(參見文末資源部分),這個應用程序包含了一個Java類(JspUtils)和類中包含一個方法eval(),這個方法有三個參數:JSP表達式、表達式的期望類型和一個JSP context對象。

Eval()方法從JSP context中取得ExpressionEvaluator并且調用evaluate()方法,通過表達式、表達式的期望類型、和一個從JSP congtext中獲得的變量。

JspUtils.eval()方法返回表達式的值。

package com.devsphere.articles.jspcache;  ...    ...    import javax.servlet.jsp.JspContext;  import javax.servlet.jsp.JspException;  import javax.servlet.jsp.PageContext;  import javax.servlet.jsp.el.ELException;  import javax.servlet.jsp.el.ExpressionEvaluator;  import java.io.IOException;public class JspUtils  {  public static Object eval(  String expr, Class type, JspContext jspContext)  throws JspException  {  try  {  if (expr.indexOf(${) == -1)  return expr;  ExpressionEvaluator evaluator= jspContext.getExpressionEvaluator();  return evaluator.evaluate(expr, type,  jspContext.getVariableResolver(), null);  } catch (ELException e)  {  throw new JspException(e);  }  }  ...  }注意:JspUtils.eval()主要封裝了標準的ExpressionEvaluator。

如果expr不包含${,JSP EL API不被調用,因為沒有JSP表達式。

創建標簽庫描述符(TLD)文件JSP標簽庫需要一個標簽庫描述符(TLD)文件來自定義標簽的命名,它們的屬性,以及操作該標簽的Java類。

jspcache.tld描述了兩個自定義標簽,擁有兩個屬性:緩存頁面片段的id和JSP scopeJSP頁面總需要被儲存的內容范圍。

只有一個屬性,即JSP表達式必須在每一次緩存片段被輸出時被賦值。

TLD文件將這兩個自定義標簽映射到CacheTag和DynamicTag類,如下所示:  TLD文件包含在Web應用描述符文件(web.xml)中,這五個文件同樣包含一個初始參數指出cache是否可用。

  理解的工作機理JSP容器為JSP頁面中的每一個標簽創建一個CacheTag實例,來對其處理。

JSP容器負責調用setJsp()、setParent()和setJspBody()方法,這是CacheTag類從SimpleTagSupport繼承而來。

JSP容器同事還為所操作標簽的每一個屬性調用setter方法。

SetId()和setScope()方法存儲屬性值到私有域,這個值已經用CacheTag()構造函數用缺省值初始化。

package com.devsphere.articles.jspcache;  xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance  xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd  version=2.4    com.devsphere.articles.jspcache.enabled              import javax.servlet.ServletContext;  import javax.servlet.jsp.JspContext;  import javax.servlet.jsp.JspException;  import javax.servlet.jsp.PageContext;  import javax.servlet.jsp.tagext.SimpleTagSupport;  import java.io.IOException;import java.io.StringWriter;  public class CacheTag extends SimpleTagSupport  {  public static final String CACHE_ENABLED  =  com.devsphere.articles.jspcache.enabled;  private String id;  private int scope;  private boolean cacheEnabled;  public CacheTag()  {  id = null;scope = PageContext.APPLICATION_SCOPE;  }public void setId(String id)  {  this.id = id;  }  public void setScope(String scope)  {  this.scope = JspUtils.checkScope(scope);  }  ...  }  setScope()方法調用JspUtils.checkScope()來校驗已經  從String轉換為int類型的scope的屬性值。

   ...public class JspUtils {   ...   public static int checkScope(String scope) {   if (page.equalsIgnoreCase(scope))   return PageContext.PAGE_SCOPE;   else if (request.equalsIgnoreCase(scope))   return PageContext.REQUEST_SCOPE;   else if (session.equalsIgnoreCase(scope))   return PageContext.SESSION_SCOPE;   else if (application.equalsIgnoreCase(scope))   return PageContext.APPLICATION_SCOPE;   else  throw new IllegalArgumentException (  Invalid scope: scope);  }}一旦CacheTag實例準備對標簽進行操作,JSP容器調用doTag()方法,用getJspContext()來獲得JSP context。

這個對象被造型為PageContext,從而可以調用getServletContext()方法。

servlet context用來獲取初始化參數的值,這個值標明緩存機制是否被啟用。

如果緩存被啟用,doTag()嘗試使用id和scope屬性值來獲得緩存頁面片段。

如果頁面片段還沒有被緩存,doTag()使用getJspBody().invoke()來執行由封裝的JSP代碼。

由JSP body產生的輸出結果緩沖在StringWriter并且被toStirng()方法獲得。

這樣,doTag()調用JSP context的setAttribute()方法新建一個JSP變量,這個變量控制可能包含JSP表達式(${})的緩存內容。

這些表達式在用jspContext.getOut().print()輸出內容前,被JspUtils.eval()賦值。

只有當緩存被啟用的時候,這些行為才發生。

否則,doTag()只是通過getJspBody().invoke(null)執行JSP body并且輸出結果不被緩存。

...  public class CacheTag extends SimpleTagSupport  {  ...  public void doTag() throws JspException, IOException  {  JspContext jspContext = getJspContext();  ServletContext application  = ((PageContext)  jspContext).getServletContext();  String cacheEnabledParam= application.getInitParameter(CACHE_ENABLED);  cacheEnabled = cacheEnabledParam != null   cacheEnabledParam.equals(true);  if (cacheEnabled)  {  String cachedOutput= (String) jspContext.getAttribute(id, scope);  if (cachedOutput == null)  {  StringWriter buffer = new StringWriter();  getJspBody().invoke(buffer);  cachedOutput = buffer.toString();  jspContext.setAttribute(id, cachedOutput, scope);  }  String evaluatedOutput = (String)  JspUtils.eval(  cachedOutput, String.class, jspContext);  jspContext.getOut().print(evaluatedOutput);  }  else  getJspBody().invoke(null);  }  ...  }注意一個單獨的JspUtils.eval()調用給所有的${} 表達式賦值。

因為一個包含了大量的${}結構的text也是一個表達式。

每一個緩存片段都可以被當作一個復雜的JSP表達式來進行處理。

    IsCacheEnabled()方法返回cacheEnabled的值,這個值已經被doTag()初始化。

IsCacheEnabled()方法返回cacheEnabled的值,這個值已經被doTag()初始化。

  ...public class CacheTag extends SimpleTagSupport  {  ...  public boolean isCacheEnabled() {  return cacheEnabled;  }  }標簽允許頁面開發者自主選擇緩存頁面片段的ID。

這使得緩存一個頁面片段可以被多個JSP頁面共享,當需要重用JSP代碼時,這是很有用處的。

但是仍然需要一些命名協議來避免可能的沖突。

通過修改CacheTag類來在自動ID內部包含URL可以避免這種副作用。

 理解在做什么每一個被一個DynamicTag類的實例處理,setExpr()方法將expr屬性值存儲到一個私有域。

DoTag()方法創建JSP表達式,在expr屬性值加上${前綴和}后綴。

然后,doTag()使用findAncestorWithClass()來查找含有標簽元素的的CacheTag handler。

如果沒有查找到或者緩存被禁用,JSP表達式被JspUtils.eval()賦值并且值被輸出。

否則,doTag()輸出無值表達式。

package com.devsphere.articles.jspcache;  import javax.servlet.jsp.JspException;  import javax.servlet.jsp.tagext.SimpleTagSupport;  import java.io.IOException;  public class DynamicTag extends SimpleTagSupport  {  private String expr;  public void setExpr(String expr)  {  this.expr = expr;  }  public void doTag() throws JspException, IOException  {  String output = ${ expr };  CacheTag ancestor = (CacheTag) findAncestorWithClass  (  this, CacheTag.class);  if (ancestor == null || !ancestor.isCacheEnabled())  output = (String) JspUtils.eval  (  output, String.class, getJspContext());  getJspContext().getOut().print(output);  }  }分析上面的代碼,大家可以注意到合作來實現一個盡可能有效率的方案。

如果緩存可用,頁面片段和由生成并被CacheTag賦值的JSP表達式一起放入緩沖器。

如果緩存被禁用,緩沖變得沒有意義,只是執行其JSP body部分,而讓DynamicTag給JSP表達式賦值。

禁用緩存有時候是必要的,特別是在開發過程期間出現內容的改變和JSP頁面被重新編譯的時候。

當然,在開發完畢的成品環境中緩存必須被啟用。

總結內容緩存是一種非常易用的改善Web應用性能的方法。

這篇文章集中討論了使用JSP表達式語言來為每一個用戶或者請求定制緩存內容。

貫穿全文的簡單介紹的標簽庫適合小型Web apps并且可以提升中等應用的性能。

對于開發大型企業級應用,則應當考慮使用支持更好的緩存機制的框架結構,而不僅僅局限于使用JSP變量。

版權聲明:本文由 毓悠雅 整理編輯。

原標題:清除緩存,清緩存

轉載注明出處:http://www.dn9ww09s.icu/program/15306.html

文章評論

    共有條評論來說兩句吧...

    用戶名:

    驗證碼:

作者推薦

  • while語法,since語法

    while語法,since語法 相關圖片while是介詞嗎另一個常見的post do while循環。。。下一個循環。在do while循環語句中重復語句塊的次數是可變的。當條件為真或條件變為真時,重復該語句。語法如下while后面動詞用法...

  • asp語法,asp語法教程

    asp語法,asp語法教程 相關圖片razor 語法下次循環使用時,需要多次執行一段代碼。語法如下:for counter=initial“value to finish”value[step incrementasp語言特點...

  • 案例分析和實例分析,qfd實例分析

    案例分析和實例分析,qfd實例分析 相關圖片autoform實例分析系統:對于JSP初學者來說,Win2003 iis6.0 J2SE 5.0,當他們談到JSP IIS時,一定要有一個大腦袋!雖然在雅加達JK2可以解決這個問題,實例分析的亮點...

  • 數組的最大值及下標,返回數組最大值的下標

    數組的最大值及下標,返回數組最大值的下標 相關圖片php數組最大值的下標本文主要介紹了PHP獲取數組最大下標的方法,包括PHP的功能,如馬克斯和數組[查找]操作數組。對于您的朋友,可以參考本文的以下示例來描述PHP獲取數組最大下標的...

  • 數據庫有哪些,數據庫

    數據庫有哪些,數據庫 相關圖片數據庫視圖SP操作access數據庫最近用JSP編寫了公司網站的示例程序,用JSP操作access數據庫,很多事情都不難,但我們不知道。^-^哈哈,現在我已經寫了一個小程SQL數據庫...

  • php gd庫,php

    php gd庫,php 相關圖片php圖像處理本文主要介紹了利用GD庫在PHP中實現遠程圖像下載的實例。本文直接給出了實現代碼。您可以參考今天的類編寫遠程圖像下載,并提前編寫PHP GD庫來實現遠程圖像下載php實戰小...

  • 保險基本原理的總結,基本原理的意思

    保險基本原理的總結,基本原理的意思 相關圖片唯物史觀三個基本原理JSP的優點是將業務邏輯處理和Web UI工作分離開來。JSP頁面將一些JSP元素插入到普通的web頁面中,根據不同的請求輸出動態文本。JSP容器負責將JSP文分子生物學的三...

  • at對進程進行調度,進程調度算法代碼

    at對進程進行調度,進程調度算法代碼 相關圖片c sort函數在我們的課程設計中,我選擇了流程調度模擬。我希望你能多看一眼,多做些評論。我很久沒發郵件了。#includeiostream.h#includestdlib.hpython...

  • gurobi使用實例,canalyzer使用實例

    gurobi使用實例,canalyzer使用實例 相關圖片使用與滿足理論的實例本文主要介紹splfix數組在phpspl標準庫中的使用實例。Splfixedarray主要處理與數組相關的主要功能,具有固定的長度和比普通數組處理速度快的特點Qt實例...

  • 服務器組件,組件正在調用服務器

    服務器組件,組件正在調用服務器 相關圖片服務器插件ASP檢測服務器安裝的組件服務器框架...

熱評文章

  • ap數據庫,ap數據庫怎么升級

    ap數據庫,ap數據庫怎么升級 相關圖片api數據庫AP plet是一個用Java語言編寫的小型應用程序。它可以嵌入到HTML中,通過WWW瀏覽器進行解釋和執行。但是,如何處理互聯網世界中大量的數據和分布在網絡各tp5數據庫增刪改查...

  • php猴子大王,php猴子選大王

    php猴子大王,php猴子選大王 相關圖片PHP猴王本文舉例說明如何解決這一問題。與您分享以供參考。具體分析如下:問題描述:一群猴子圍成一圈,依次按1、2、…、N。然后從第一個開始數數,數到m,把它踢出圓圈,從后猴...

  • asp語法,asp語法教程

    asp語法,asp語法教程 相關圖片razor 語法If語句使變量或其他類型的數據能夠作出決定的方法。例如,您可能有一個腳本來檢查布爾值是真是假,或者變量是否包含數字或字符串值。如果邏輯條件為true,則使用ifasp語言...

  • 圖表,圖表的應用

    圖表,圖表的應用 相關圖片表格動態圖表FusionCharts free下載地址:http://www.FusionCharts.com/goods/FusionCharts-free/next,在如何做動態圖表...

  • 文件系統支持對文件權限的設置,win10文件系統權限

    文件系統支持對文件權限的設置,win10文件系統權限 相關圖片linux查看文件權限在iis7.0上,以fastcgi模式配置PHP運行環境。在測試PHP程序能夠正常運行后,部署PHP程序并導入程序的原始數據和配置信息。很快就會有問題。讓我們把Windows設置文件權限...

  • 靜態數組賦值,創建靜態數組

    靜態數組賦值,創建靜態數組 相關圖片vb靜態數組這是假設您知道數組的基本特性,所以讓我們考慮如何在VBScript中處理ASP,。VBScript中的數組是0,這意味著數組元素的索引總是從0開始。0索引表示數靜態數組初始化為0...

  • 外部全局數組,超全局數組

    外部全局數組,超全局數組 相關圖片定義一vb個全局數組今天,我的同學遇到了一個C語言中的全局數組和局部數組的問題。經過很長一段時間的打牌,我第一次沒有看到問題。現在我來解決這個問題并給出解決辦法。問題...

  • php gd庫,php

    php gd庫,php 相關圖片php圖像處理本文主要介紹了在PHP中使用GD庫下載網頁中的所有圖片。本文直接給出了實現代碼。您可以參考前面的PHP教程,并說phpgd庫可以下載遠程圖片,但它只下載圖片。原php實戰小項...

  • 系統失敗自動重啟,收集錯誤信息自動重啟

    系統失敗自動重啟,收集錯誤信息自動重啟 相關圖片win10關機自動重啟本文主要介紹了利用PHP腳本監控nginx502錯誤并自動重啟PHP FPM。本文直接給出了實現代碼,然后在Cron中執行。您可以不時地參考最近的服務器nginwin10 自動重啟...

  • php 數組轉字符串,php把數組字符串變成數組

    php 數組轉字符串,php把數組字符串變成數組 相關圖片將數組變成字符串本文以一個實例說明PHP解析字符串數組的方法。與您分享以供參考。具體如下:?12345678910121314151617181920122?PHP$STR=1php字符串替換...

關注微信

变脸官网查询