频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

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

来源: 作者:佚名 出处:巧巧读书 2008-03-25 进入讨论组

JSP 变量易于使用,对于简单的Web apps,这是一个不错的内容缓存方案。然而,如果应用程序产生大量的动态内容,没有对缓存大小的控制无疑是一个问题。

一种专用的缓存框架结构能够提供一个更加有力的方案,允许对缓存的监视,限制缓存大小,控制缓存策略,等等……

使用JSP 2.0表达式语言API

JSP容器(例如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描述了两个自定义标签,<jc:cache>拥有两个属性:缓存页面片段的id和JSP scope—JSP页面总需要被储存的内容范围。<jc:dynamic>只有一个属性,即JSP表达式必须在每一次缓存片段被输出时被赋值。TLD文件将这两个自定义标签映射到CacheTag和DynamicTag类,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>

<taglib 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-jsptaglibrary_2_0.xsd"  version="2.0">  
<tlib-version>1.0</tlib-version>  
<short-name>jc</short-name>  
<uri>http://devsphere.com/articles/jspcache</uri>  
<tag>  
<name>cache</name>  
<tag-class>com.devsphere.articles.jspcache.CacheTag</tag-class>  
<body-content>scriptless</body-content>  
<attribute>  <name>id</name>  <required>true</required>  
<rtexprvalue>true</rtexprvalue>  </attribute>  <attribute>  
<name>scope</name>  <required>false</required>  
<rtexprvalue>false</rtexprvalue>  </attribute>  
</tag>  <tag>  <name>dynamic</name>  <tag-class>

com.devsphere.articles.jspcache.DynamicTag</tag-class> 
 
<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>

理解<jc:cache>的工作机理

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);  }}
 
更多文章 更多内容请看Jsp完全攻略专题JSP教程专栏jsp文摘专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
讨论组问题推荐
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章