dedecms织梦内容管理系统    
首页 | java | C/C++ | PHP | 操作系统 | ajax | 脚本编程 | 安全技术 | 本站下载页 | flex | CRM | 专题 | QQ群 | 测试中心 | 会员中心 | 积分规则
  当前位置:主页>java>jsp>文章内容
JSP 2.0下的动态内容缓存分析讲解
来源:未知     作者:    

  在Web应用中,内容缓存是最普通的优化技术之一,并且能够很容易地实现。例如,可以使用一个自定义地JSP标签——我们将之命名为<jc:cache>——由<jc:cache>和</jc:cache>将每一个需要被缓存的页面片段封装起来。任何自定义标签可以控制它所包含部分 (也即预先封装的页面片段)在何时执行,并且动态输出结果可以被捕获。<jc:cache>标签使得JSP容器(例如)只生成内容一次,作为应用程序范围内的JSP变量,来存储每一个缓存片段。每次JSP页面被执行时,自定义标签将缓存页面片段载入而无需再次执行代码来生成输出结果。作为Jakarta工程的一个部分,标签库的开发使用了这项技术。当被缓存内容无需被每一个用户或者请求所定制的时候,它工作的十分良好。
  
  这篇文章对上面描述的技术做了改进,通过使用JSP 2.0表达式语言(EL),允许JSP页面为每一个请求和用户定制缓存内容。缓存页面片段可以包含未被JSP容器赋值的JSP表达式,在每一次页面被执行时,由自定义标签来确定这些表达式的值。因此,动态内容的建立被最优化,但是缓存片段可以含有部分由每一个请求使用本机JSP表达式语言产生的内容。通过 2.0 EL API的帮助,开发者可以用表达式语言来使之成为可能。
  
  内容缓存VS数据缓存
  
  内容缓存不是唯一的选择。例如, 从中提取的数据同样可以被缓存。事实上,由于存储的信息中不包含HTML markup,以及要求较少的内存,数据缓存可能更加高效率。然而在很多情况下,内存缓存更容易实现。假设在某个案例总,一个应用由大量事务对象,占用重要的CPU资源,产生复杂的数据,并且用JSP页面来呈现这些数据。工作一切良好,直到某天突然地服务器的负载增加,需要一个紧急解决方案。这时在事务对象和呈现表达层之间建立一个缓存层,时一个非常不错和有效的方案。但是必须非常快速和流畅地修改缓存动态内容的JSP页面。相对于简单的页面编辑,应用程序的业务逻辑变化通常要求更多的工作量和测试;另外,如果一个页面从多个复合源聚合信息时,Web层仅有少量的改变。问题在于,当缓存信息变得失去时效时,缓存空间需要被释放,而事务对象应该知道何时发生这种情况。然而,选择实现内容缓存还是数据缓存,或者其他的优化技术,有很多不得不考虑的因素,有时是所开发的程序所特殊要求的。
  
  数据缓存和内容缓存没有必要互相排斥,它们可以一起使用。例如,在数据库驱动的应用中;从中提取出来的数据,和呈现该数据的HTML分别被缓存起来。这与使用JSP实时生成的模板有些相似。这篇文章中讨论的基于EL API技术说明如何使用 EL来将数据载入到呈现模板中。
  
  使用变量缓存动态内容
  
  每当实现一个缓存机制是,都需要一个存储缓存对象的方法,在这篇文章中涉及的是String类型的对象。 一种选择是使用一个对象——缓存框架结构,或者使用 maps来实现自定义的缓存方案。JSP已经拥有了称为“scoped attributes”或“JSP variables”来提供ID——object映射,这正是缓存机制所需要的。对于使用page或者request scope,这是没有意义的,而在应用范围内,这是一个很好的存储缓存内容的位置, 因为它被所有的用户和页面共享。当每一个用户需要单独缓存时, scope也可以被使用,但这不是很有效率。JSTL标签库可以被是与那个来缓存内容,通过使用变量正如下例所示:
  
  <%@ taglib prefix="c" uri="http://.sun.com//jstl/core" %><c:if test="${empty cachedFragment}">
  <c:set var="cachedFragment" scope="application">
  ...
  </c:set></c:if>
  
  缓存页面片段用下列语句输出结果:
  ${applicationScope.cachedFragment}
  
  当缓存片段需要被每一个请求所定制的时候,到底发生了什么?例如,如果希望包含一个计数器,需要缓存两个片段:
  <%@ taglib prefix="c" uri="http://.sun.com//jstl/core" %><c:if test="${sessionScope.counter == null}">  <c:set var="counter" scope="session" value="0"/></c:if><c:set var="counter" value="${counter+1}" scope=""/><c:if test="${empty cachedFragment1}">
  <c:set var="cachedFragment1" scope="application">
  ...
  </c:set></c:if><c:if test="${empty cachedFragment2}">
  <c:set var="cachedFragment2" scope="application">
  ...
  </c:set></c:if>
  
  可以使用下面语句输出缓存内容:
  ${cachedFragment1} ${counter} ${cachedFragment2}
  
  通过专门的标签库的帮助,需要定制的页面片段的缓存变得异常容易了。上面已经提及,缓存内容可以被开始标签(<jc:cache>)和结尾标签(</jc:cache>)封装起来。而每一个定制可以使用另一个标签(<jc:dynamic expr="..."/>)输出一个JSP表达式(${...})来表现。动态内容用JSP表达式缓存并在每一次缓存内容被输出时赋值。在下面的部分可以看到这是如何实现的。Counter.缓存了一个包含计数器的页面片段,当每一次用户刷新这个页面的时候计数器会自动+1。
  <%@ taglib prefix="c" uri="http://.sun.com/jsp/jstl/core" %><%@ taglib prefix="jc" uri="http://devsphere.com/articles/cache" %><c:if test="${Scope.counter == null}">
  <c:set var="counter" scope="session" value="0"/></c:if><c:set var="counter" value="${counter+1}" scope=""/><jc:cache id="cachedFragmentWithCounter">
  ... <jc:dynamic expr="Scope.counter"/>
  ...</jc:cache>
  
   变量易于使用,对于简单的Web apps,这是一个不错的内容缓存方案。然而,如果应用程序产生大量的动态内容,没有对缓存大小的控制无疑是一个问题。一种专用的缓存框架结构能够提供一个更加有力的方案,允许对缓存的监视,限制缓存大小,控制缓存策略,等等……
  
  使用 2.0表达式语言API
  
  JSP容器(例如)对应用EL API的页面中的表达式予以赋值,并且可以被代码所使用。这允许在Web页面外应用JSP EL作开发,例如,对文件、基于文本的资源以及自定义脚本。当需要控制何时对Web页面中的表达式进行赋值或者书写与之相关的表达式时,EL API同样是有用的。例如,缓存页面片段可以包含自定义表达式,并且当每一次缓存内容被输出时,EL API将用来给这些表达式赋值或者重新赋值。
  
  文章提供了一个例子程序(参见文末资源部分),这个应用程序包含了一个类(JspUtils)和类中包含一个方法eval(),这个方法有三个参数:JSP表达式、表达式的期望类型和一个JSP context对象。Eval()方法从JSP context中取得ExpressionEvaluator并且调用evaluate()方法,通过表达式、表达式的期望类型、和一个从JSP congtext中获得的变量。Utils.eval()方法返回表达式的值。
  package com.devsphere.articles.cache;
  import x..jsp.Context;
  import x..jsp.Exception;
  import x...PageContext;
  import x...el.ELException;
  import x...el.ExpressionEvaluator;
  import .io.IOException;public class Utils {
  public static Object eval(
  String expr, Class type, JspContext Context)
  throws Exception {
  try {
  if (expr.indexOf("${") == -1)
  return expr;
  ExpressionEvaluator evaluator
  = Context.getExpressionEvaluator();
  return evaluator.evaluate(expr, type,
  Context.getVariableResolver(), null);
  } catch (ELException e) {
  throw new Exception(e);
  }
  }
  ...}
  
  注意:JspUtils.eval()主要封装了标准的ExpressionEvaluator。如果expr不包含${,JSP EL API不被调用,因为没有表达式。

[1]  

 

 

上一篇:用PHP制作zip压缩程序   下一篇:入侵基于JSP+Tomcat的Web网站实录
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论
  热点文章
·JSP入门实例教程
·什么是Servlet
·JSP常用内置对象使用说明
·JSP自定义标签由浅到深详细讲解
·JSP自定义标签由浅到深详细讲解
·Java Servlet技术
·Javax.servlet API的特征
·一个简单的jsp注册页面
·JSTL操作数据库示例
·JSP入门实例教程13-MVC模式
·JSP入门实例教程12-jstl处理数
·JSP入门实例教程11-jstl处理xml
  相关文章
·用PHP制作zip压缩程序
·入侵基于JSP+Tomcat的Web网站实
·多个域名绑定一个空间互不影响
·JSP报表打印的一种简单解决方案
·怎样在php中使用PDF文档功能
·JSP/Servlet的重定向技术综述
·一个个人网页自动化生成系统(2
·JSP/Servlet构建三层管理信息系
·利用weblogic的POOL(连接池)连
·用缓冲技术提高JSP程序的性能和
·Jsp中调用Oracle存储过程的小例
·利用JSP 2.0开发Web应用程序
  相关信息
copy right @ 百家拳软件项目研究室 2007 辽ICP备07011763