欢迎来到HELLO素材网! 南京网站制作选择顺炫科技
丰富的DIV CSS模版、JS,jQuery特效免费提供下载
当前位置:主页 > 建站教程 > 网站制作教程 >

JSP 2.0下的动态内容缓存剖析讲解

发表于2019-04-24 02:06| 次阅读| 来源网络整理| 作者session

摘要:JSP 2.0下的动态内容缓存剖析讲解

JSP 2.0下的动态内容缓存剖析讲解

  在Web运用中,内容缓存是最一般的优化技术之一,并且可以很容易地完成。例如,可能利用一个自定义地JSP标签——咱们将之命名为<jc:cache>——由<jc:cache>和</jc:cache>将每一个需求被缓存的页面片段封装起来。任何自定义标签可能控制它所蕴含局部(也即预先封装的页面片段)在何时执行,并且动态输出后果可能被捕获。<jc:cache>标签使得JSP容器(例如Tomcat)只生成内容一次,作为运用程序范围内的JSP变量,来存储每一个缓存片段。每次JSP页面被执行时,自定义标签将缓存页面片段载入而无需再次执行JSP代码来生成输出后果。作为Jakarta工程的一个局部,标签库的开发利用了这项技术。当被缓存内容无需被每一个用户或许申请所定制的时分,它工作的非常良好。
  
  这篇文章对上面形容的技术做了改进,经过利用JSP2.0表达式言语(EL),容许JSP页面为每一个申请和用户定制缓存内容。缓存页面片段可能蕴含未被JSP容器赋值的JSP表达式,在每一次页面被执行时,由自定义标签来确定这些表达式的值。因此,动态内容的建设被最优化,然而缓存片段可能含有局部由每一个申请利用本机JSP表达式言语产生的内容。经过JSP2.0ELAPI的协助,Java开发者可能用表达式言语来使之成为能够。
  
  内容缓存VS数据缓存
  
  内容缓存不是惟一的抉择。例如,从数据库中提取的数据异样可能被缓存。理想上,因为存储的信息中不蕴含HTMLmarkup,以及要求较少的内存,数据缓存能够愈加高效率。但是在很多情况下,内存缓存更容易完成。假定在某个案例总,一个运用由大量事务对象,占用重要的CPU资源,产生简单的数据,并且用JSP页面来呈现这些数据。工作所有良好,直到某天忽然地服务器的负载添加,需求一个紧急处理计划。这时在事务对象和呈现表达层之间建设一个缓存层,时一个十分不错和有效的计划。然而必须十分快速和流利地修正缓存动态内容的JSP页面。相对于简略的JSP页面编辑,运用程序的业务逻辑变化通常要求更多的工作量和测试;另外,假设一个页面从多个复合源聚合信息时,Web层仅有大批的扭转。成绩在于,当缓存信息变得得到时效时,缓存空间需求被监禁,而事务对象应该知道何时发生这种情况。但是,抉择完成内容缓存还是数据缓存,或许其余的优化技术,有很多不得不思考的要素,有时是所开发的程序所特殊要求的。
  
  数据缓存和内容缓存没有必要互相排斥,它们可能一同利用。例如,在数据库驱动的运用中;从数据库中提取进去的数据,和呈现该数据的HTML分别被缓存起来。这与利用JSP实时生成的模板有些相似。这篇文章中探讨的基于ELAPI技术阐明如何利用JSPEL来将数据载入到呈现模板中。
  
  利用JSP变量缓存动态内容
  
  每当完成一个缓存机制是,都需求一个存储缓存对象的方法,在这篇文章中触及的是String类型的对象。一种抉择是利用一个对象——缓存框架构造,或许利用Javamaps来完成自定义的缓存计划。JSP已经领有了称为“scopedattributes”或“JSPvariables”来提供ID——object映射,这正是缓存机制所需求的。对于利用page或许requestscope,这是没无心义的,而在运用范围内,这是一个很好的存储缓存内容的地位,由于它被一切的用户和页面共享。当每一个用户需求单独缓存时,Sessionscope也可能被利用,但这不是很有效率。JSTL标签库可能被是与那个来缓存内容,经过利用JSP变量正如下例所示:
  
  <%@taglibprefix="c"uri=""%><c:iftest="${emptycachedFragment}">
  
  <c:setvar="cachedFragment"scope="application">
  
  ...
  
  </c:set></c:if>
  
  缓存页面片段用下列语句输出后果:
  
  ${applicationScope.cachedFragment}
  
  当缓存片段需求被每一个申请所定制的时分,到底发生了什么?例如,假设宿愿蕴含一个计数器,需求缓存两个片段:
  
  <%@taglibprefix="c"uri=""%><c:iftest="${sessionScope.counter==null}"><c:setvar="counter"scope="session"value="0"/></c:if><c:setvar="counter"value="${counter+1}"scope="session"/><c:iftest="${emptycachedFragment1}">
  
  <c:setvar="cachedFragment1"scope="application">
  
  ...
  
  </c:set></c:if><c:iftest="${emptycachedFragment2}">
  
  <c:setvar="cachedFragment2"scope="application">
  
  ...
  
  </c:set></c:if>
  
  可能利用下面语句输出缓存内容:
  
  ${cachedFragment1}${counter}${cachedFragment2}
  
  经过专门的标签库的协助,需求定制的页面片段的缓存变得同样容易了。上面已经提及,缓存内容可能被末尾标签(<jc:cache>)和开头标签(</jc:cache>)封装起来。而每一个定制可能利用另一个标签(<jc:dynamicexpr="..."/>)输出一个JSP表达式(${...})来体现。动态内容用JSP表达式缓存并在每一次缓存内容被输出时赋值。在下面的局部可能看到这是如何完成的。Counter.jsp缓存了一个蕴含计数器的页面片段,当每一次用户刷新这个页面的时分计数器会主动+1。
  
  <%@taglibprefix="c"uri=""%><%@taglibprefix="jc"uri=""%><c:iftest="${sessionScope.counter==null}">
  
  <c:setvar="counter"scope="session"value="0"/></c:if><c:setvar="counter"value="${counter+1}"scope="session"/><jc:cacheid="cachedFragmentWithCounter">
  
  ...<jc:dynamicexpr="sessionScope.counter"/>
  
  ...</jc:cache>
  
  JSP变量易于利用,对于简略的Webapps,这是一个不错的内容缓存计划。但是,假设运用程序产生大量的动态内容,没有对缓存大小的控制无疑是一个成绩。一种公用的缓存框架构造可以提供一个愈加有力的计划,容许对缓存的监督,限度缓存大小,控制缓存策略,等等……
  
  利用JSP2.0表达式言语API
  
  JSP容器(例如Tomcat)对运用ELAPI的JSP页面中的表达式予以赋值,并且可能被Java代码所利用。这容许在Web页面外运用JSPEL作开发,例如,对XML文件、基于文本的资源以及自定义脚本。当需求控制何时对Web页面中的表达式停止赋值或许书写与之相干的表达式时,ELAPI异样是有用的。例如,缓存页面片段可能蕴含自定义JSP表达式,并且当每一次缓存内容被输出时,ELAPI将用来给这些表达式赋值或许重新赋值。
  
  文章提供了一个例子程序(参见文末资源局部),这个运用程序蕴含了一个Java类(JspUtils)和类中蕴含一个方法eval(),这个方法有三个参数:JSP表达式、表达式的希冀类型和一个JSPcontext对象。Eval()方法从JSPcontext中取得ExpressionEvaluator并且调用evaluate()方法,经过表达式、表达式的希冀类型、和一个从JSPcongtext中获得的变量。JspUtils.eval()方法前往表达式的值。
  
  packagecom.devsphere.articles.jspcache;
  
  importjavax.servlet.jsp.JspContext;
  
  importjavax.servlet.jsp.JspException;
  
  importjavax.servlet.jsp.PageContext;
  
  importjavax.servlet.jsp.el.ELException;
  
  importjavax.servlet.jsp.el.ExpressionEvaluator;
  
  importjava.io.IOException;publicclassJspUtils{
  
  publicstaticObjecteval(
  
  Stringexpr,Classtype,JspContextjspContext)
  
  throwsJspException{
  
  try{
  
  if(expr.indexOf("${")==-1)
  
  returnexpr;
  
  ExpressionEvaluatorevaluator
  
  =jspContext.getExpressionEvaluator();
  
  returnevaluator.evaluate(expr,type,
  
  jspContext.getVariableResolver(),null);
  
  }catch(ELExceptione){
  
  thrownewJspException(e);
  
  }
  
  }
  
  ...}
  
  留意:JspUtils.eval()次要封装了标准的ExpressionEvaluator。假设expr不蕴含${,JSPELAPI不被调用,由于没有JSP表达式。