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

廉40

廉40

2016-02-19 14:00

图老师设计创意栏目是一个分享最好最实用的教程的社区,我们拥有最用心的各种教程,今天就给大家分享JSP 2.0下的动态内容缓存分析讲解的教程,热爱PS的朋友们快点看过来吧!

在Web应用中,内容缓存是最普通的优化技术之一,并且能够很容易地实现。例如,可以使用一个自定义地JSP标签——我们将之命名为<jc:cache>——由<jc:cache>和</jc:cache>将每一个需要被缓存的页面片段封装起来。任何自定义标签可以控制它所包含部分 (也即预先封装的页面片段)在何时执行,并且动态输出结果可以被捕获。<jc:cache>标签使得JSP容器(例如Tomcat)只生成内容一次,作为应用程序范围内的JSP变量,来存储每一个缓存片段。每次JSP页面被执行时,自定义标签将缓存页面片段载入而无需再次执行JSP代码来生成输出结果。作为Jakarta工程的一个部分,标签库的开发使用了这项技术。当被缓存内容无需被每一个用户或者请求所定制的时候,它工作的十分良好。
  
  这篇文章对上面描述的技术做了改进,通过使用JSP 2.0表达式语言(EL),允许JSP页面为每一个请求和用户定制缓存内容。缓存页面片段可以包含未被JSP容器赋值的JSP表达式,在每一次页面被执行时,由自定义标签来确定这些表达式的值。因此,动态内容的建立被最优化,但是缓存片段可以含有部分由每一个请求使用本机JSP表达式语言产生的内容。通过JSP 2.0 EL API的帮助,Java开发者可以用表达式语言来使之成为可能。
  
  
  
  内容缓存不是唯一的选择。例如, 从数据库中提取的数据同样可以被缓存。事实上,由于存储的信息中不包含HTML markup,以及要求较少的内存,数据缓存可能更加高效率。然而在很多情况下,内存缓存更容易实现。假设在某个案例总,一个应用由大量事务对象,占用重要的CPU资源,产生复杂的数据,并且用JSP页面来呈现这些数据。工作一切良好,直到某天突然地服务器的负载增加,需要一个紧急解决方案。这时在事务对象和呈现表达层之间建立一个缓存层,时一个非常不错和有效的方案。但是必须非常快速和流畅地修改缓存动态内容的JSP页面。相对于简单的JSP页面编辑,应用程序的业务逻辑变化通常要求更多的工作量和测试;另外,如果一个页面从多个复合源聚合信息时,Web层仅有少量的改变。问题在于,当缓存信息变得失去时效时,缓存空间需要被释放,而事务对象应该知道何时发生这种情况。然而,选择实现内容缓存还是数据缓存,或者其他的优化技术,有很多不得不考虑的因素,有时是所开发的程序所特殊要求的。
  
  数据缓存和内容缓存没有必要互相排斥,它们可以一起使用。例如,在数据库驱动的应用中;从数据库中提取出来的数据,和呈现该数据的HTML分别被缓存起来。这与使用JSP实时生成的模板有些相似。这篇文章中讨论的基于EL API技术说明如何使用JSP EL来将数据载入到呈现模板中。
  
  
  
  每当实现一个缓存机制是,都需要一个存储缓存对象的方法,在这篇文章中涉及的是String类型的对象。 一种选择是使用一个对象——缓存框架结构,或者使用Java maps来实现自定义的缓存方案。JSP已经拥有了称为“scoped attributes”或“JSP variables”来提供ID——object映射,这正是缓存机制所需要的。对于使用page或者request scope,这是没有意义的,而在应用范围内,这是一个很好的存储缓存内容的位置, 因为它被所有的用户和页面共享。当每一个用户需要单独缓存时,Session scope也可以被使用,但这不是很有效率。JSTL标签库可以被是与那个来缓存内容,通过使用JSP变量正如下例所示:
  
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><c:if test="${empty cachedFragment}">
  <c:set var="cachedFragment" scope="application">
  ...
  </c:set></c:if>
  
  缓存页面片段用下列语句输出结果:
  ${applicationScope.cachedFragment}
  
  当缓存片段需要被每一个请求所定制的时候,到底发生了什么?例如,如果希望包含一个计数器,需要缓存两个片段:
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/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="session"/><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.jsp缓存了一个包含计数器的页面片段,当每一次用户刷新这个页面的时候计数器会自动+1。
  <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@ taglib prefix="jc" uri="http://devsphere.com/articles/jspcache" %><c:if test="${sessionScope.counter == null}">
  <c:set var="counter" scop

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/webkaifa/)<body-content>empty</body-content>
  <attribute>
  <name>expr</name>
  <required>true</required>
  <rtexprvalue>false</rtexprvalue>
  </attribute>
  </tag></taglib>
  
  TLD文件包含在Web应用描述符文件(web.xml)中,这五个文件同样包含一个初始参数指出cache是否可用。
  <?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  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">
  <context-param>
  <param-name>com.devsphere.articles.jspcache.enabled</param-name>
  <param-value>true</param-value>
  </context-param>
  <jsp-config>
  <taglib>
  <taglib-uri>http://devsphere.com/articles/jspcache</taglib-uri>
  <taglib-location>/WEB-INF/jspcache.tld</taglib-location>
  </taglib>
  </jsp-config></web-app>
  
  
  
  JSP容器为JSP页面中的每一个<jc:cache>标签创建一个CacheTag实例,来对其处理。JSP容器负责调用setJsp()、setParent()和setJspBody()方法,这是CacheTag类从SimpleTagSupport继承而来。JSP容器同事还为所操作标签的每一个属性调用setter方法。SetId()和setScope()方法存储属性值到私有域,这个值已经用CacheTag()构造函数用缺省值初始化。
  
  package com.devsphere.articles.jspcache;
  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()来执行由<jc:cache>和</jc:cache>封装的JSP代码。由JSP body产生的输出结果缓冲在Str

期间出现内容的改变和JSP页面被重新编译的时候。当然,在开发完毕的成品环境中缓存必须被启用。
  
  
  
  内容缓存是一种非常易用的改善Web应用性能的方法。这篇文章集中讨论了使用JSP表达式语言来为每一个用户或者请求定制缓存内容。贯穿全文的简单介绍的标签库适合小型Web apps并且可以提升中等应用的性能。对于开发大型企业级应用,则该考虑使用支持更好的缓存机制的框架结构,而不仅是使用JSP变量。但是了解基于EL API的定制技术无疑是不无裨益的。
展开更多 50%)
分享

猜你喜欢

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

Web开发
JSP 2.0下的动态内容缓存分析讲解

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

Web开发
深入讲解JSP 2.0下的动态内容缓存技术

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

详解JSP 2.0下的动态内容缓存

Web开发
详解JSP 2.0下的动态内容缓存

JSP显示内容缓存技巧

Java JAVA基础
JSP显示内容缓存技巧

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

JSP下动态INCLUDE与静态INCLUDE的区别分析

Web开发
JSP下动态INCLUDE与静态INCLUDE的区别分析

JSP由浅入深(3)—— 通过表达式增加动态内容

Java JAVA基础
JSP由浅入深(3)—— 通过表达式增加动态内容

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

作业我们分手吧 试卷丈母娘也不喜欢我 - QQ搞笑分组

作业我们分手吧 试卷丈母娘也不喜欢我 - QQ搞笑分组

新手入门:关于Java的Classpath详解

新手入门:关于Java的Classpath详解
下拉加载更多内容 ↓