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

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

来源: 作者:佚名 出处:巧巧读书 2008-03-25 进入讨论组
上一页 1 2 3 

一旦CacheTag实例准备对标签进行操作,JSP容器调用doTag()方法,用getJspContext()来获得JSP context。这个对象被造型为PageContext,从而可以调用getServletContext()方法。servlet context用来获取初始化参数的值,这个值标明缓存机制是否被启用。

如果缓存被启用,doTag()尝试使用id和scope属性值来获得缓存页面片段。如果页面片段还没有被缓存,doTag()使用getJspBody().invoke()来执行由<jc:cache>和</jc:cache>封装的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;  
}
}

<jc:cache>标签允许页面开发者自主选择缓存页面片段的ID。这使得缓存一个页面片段可以被多个JSP页面共享,当需要重用JSP代码时,这是很有用处的。但是仍然需要一些命名协议来避免可能的冲突。通过修改CacheTag类来在自动ID内部包含URL可以避免这种副作用。 

理解<jc:dynamic>在做什么

每一个<jc:dynamic>被一个DynamicTag类的实例处理,setExpr()方法将expr属性值存储到一个私有域。DoTag()方法创建JSP表达式,在expr属性值加上${前缀和}后缀。然后,doTag()使用findAncestorWithClass()来查找含有<jc:dynamic>标签元素的<jc:cache>的CacheTag handler。如果没有查找到或者缓存被禁用,JSP表达式被JspUtils.eval()赋值并且值被输出。否则,doTag()输出无值表达式。

package com.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);  
}
}

分析上面的代码,大家可以注意到<jc:cache>和<jc:dynamic>合作来实现一个尽可能有效率的方案。如果缓存可用,页面片段和由<jc:dynamic>生成并被CacheTag赋值的JSP表达式一起放入缓冲器。如果缓存被禁用,缓冲变得没有意义,<jc:cache>只是执行其JSP body部分,而让DynamicTag给JSP表达式赋值。禁用缓存有时候是必要的,特别是在开发过程期间出现内容的改变和JSP页面被重新编译的时候。当然,在开发完毕的成品环境中缓存必须被启用。

总结

内容缓存是一种非常易用的改善Web应用性能的方法。这篇文章集中讨论了使用JSP表达式语言来为每一个用户或者请求定制缓存内容。贯穿全文的简单介绍的标签库适合小型Web apps并且可以提升中等应用的性能。对于开发大型企业级应用,则应当考虑使用支持更好的缓存机制的框架结构,而不仅仅局限于使用JSP变量。

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