知识大全 深入讲解JSP 2.0下的动态内容缓存技术

Posted 表达式

篇首语:女人错过了那个想嫁给的男人,就会变得挑剔,男人错过了那个他最想娶的女人,就会变得随意。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 深入讲解JSP 2.0下的动态内容缓存技术相关的知识,希望对你有一定的参考价值。

深入讲解JSP 2.0下的动态内容缓存技术  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  内容缓存是Web应用中最普通的优化技术之一 例如 可以使用一个自定义地JSP标签——我们将之命名为 ——由 将每一个需要被缓存的页面片段封装起来 任何自定义标签可以控制它所包含部分 (也即预先封装的页面片段)在何时执行 并且动态输出结果可以被捕获 标签使得JSP容器(例如Tomcat)只生成内容一次 作为应用程序范围内的JSP变量 来存储每一个缓存片段 每次JSP页面被执行时 自定义标签将缓存页面片段载入而无需再次执行JSP代码来生成输出结果 作为Jakarta工程的一个部分 标签库的开发使用了这项技术 当被缓存内容无需被每一个用户或者请求所定制的时候 它工作的十分良好

  这篇文章对上面描述的技术做了改进 通过使用JSP 表达式语言(EL) 允许JSP页面为每一个请求和用户定制缓存内容 缓存页面片段可以包含未被JSP容器赋值的JSP表达式 在每一次页面被执行时 由自定义标签来确定这些表达式的值 因此 动态内容的建立被最优化 但是缓存片段可以含有部分由每一个请求使用本机JSP表达式语言产生的内容 通过JSP 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”来提供ID——object映射 这正是缓存机制所需要的 对于使用page或者request scope 这是没有意义的 而在应用范围内 这是一个很好的存储缓存内容的位置 因为它被所有的用户和页面共享 当每一个用户需要单独缓存时 Session scope也可以被使用 但这不是很有效率 JSTL标签库可以被是与那个来缓存内容 通过使用JSP变量正如下例所示

  

  

  

  

  

  缓存页面片段用下列语句输出结果

  $applicationScope cachedFragment

  当缓存片段需要被每一个请求所定制的时候 到底发生了什么?

  例如 如果希望包含一个计数器 需要缓存两个片段

  

  

  

  

  

  

  

  

  

  

  

  可以使用下面语句输出缓存内容

  $cachedFragment $counter $cachedFragment  通过专门的标签库的帮助 需要定制的页面片段的缓存变得异常容易了 上面已经提及 缓存内容可以被开始标签( )和结尾标签( )封装起来 而每一个定制可以使用另一个标签( )输出一个JSP表达式($ )来表现 动态内容用JSP表达式缓存并在每一次缓存内容被输出时赋值 在下面的部分可以看到这是如何实现的 Counter jsp缓存了一个包含计数器的页面片段 当每一次用户刷新这个页面的时候计数器会自动+

  

  

  

  

   JSP 变量易于使用 对于简单的Web apps 这是一个不错的内容缓存方案 然而 如果应用程序产生大量的动态内容 没有对缓存大小的控制无疑是一个问题 一种专用的缓存框架结构能够提供一个更加有力的方案 允许对缓存的监视 限制缓存大小 控制缓存策略 等等……使用JSP 表达式语言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 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("$") == )  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 scope—JSP页面总需要被储存的内容范围 只有一个属性 即JSP表达式必须在每一次缓存片段被输出时被赋值 TLD文件将这两个自定义标签映射到CacheTag和DynamicTag类 如下所示

  TLD文件包含在Web应用描述符文件(web xml)中 这五个文件同样包含一个初始参数指出cache是否可用

  理解 的工作机理JSP容器为JSP页面中的每一个 标签创建一个CacheTag实例 来对其处理 JSP容器负责调用setJsp() setParent()和setJspBody()方法 这是CacheTag类从SimpleTagSupport继承而来 JSP容器同事还为所操作标签的每一个属性调用setter方法 SetId()和setScope()方法存储属性值到私有域 这个值已经用CacheTag()构造函数用缺省值初始化 package devsphere articles jspcache;

  xmlns:xsi="

  xsi:schemaLocation="

  version=" ">  

   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  =

  " 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 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);

  

cha138/Article/program/Java/Javascript/201311/25492

相关参考

知识大全 JSP技术优缺点深入分析[6]

JSP技术优缺点深入分析[6]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JSP的拥护者会很

知识大全 JSP技术优缺点深入分析[3]

JSP技术优缺点深入分析[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  工作和重复工作  

知识大全 JSP技术优缺点深入分析[4]

JSP技术优缺点深入分析[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  为了演示将Java

知识大全 JSP技术优缺点深入分析[1]

JSP技术优缺点深入分析[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  作为一名资深的Ja

知识大全 JSP技术优缺点深入分析[5]

JSP技术优缺点深入分析[5]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  可移植性和语言锁定

知识大全 JSP技术优缺点深入分析[2]

JSP技术优缺点深入分析[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  清单要比清单更加复

知识大全 动态网页制作技术JSP与ASP的比较p-

动态网页制作技术JSP与ASP的比较p-  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  总的来讲

知识大全 深入Nginx + PHP 缓存详解

深入Nginx+PHP缓存详解  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!以下是对Nginx中的

知识大全 详细讲解JSP自定义标签

详细讲解JSP自定义标签  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  &n

知识大全 详细讲解JSP访问数据库的方法

详细讲解JSP访问数据库的方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JSP(JavaS