打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Java Dreams

Tapestry之Cache组件

有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容cache住,当有新的请求时,我们就responsecache,这样可以减少服务器的负担,还可以提高性能。其中oscache已经可以实现页面的cache和页面部分cache。oscache使用jsptags来实现局部cache的。拿到Tapestry中肯定是行不通的。在同事的提醒下,想到写这个Tapestry的cache组件来达到重用的目的。

 

说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。

<span jwcid="@Cache" cacheProvider="ognl:cacheProvider" updateCondition="ognl:needUpdate">

    //Cache body, which is the content you want to cache.

</span>

这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE component-specification PUBLIC
"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">

<component-specificationallow-body="yes" allow-informal-parameters="no"class="com.live.spaces.dengyin2000.tapestry.tfancomponents.components.Cache">
   <description>
   Cache component, this component can inclue any content as its body, and cache its body.
    This is useful in rarely updated content.
    </description>
<parameter name="updateCondition" required="no" default-value="false">
    <description>
     The flag that need to refresh cache, it would casue tapestry render not use the cache.
    </description>
</parameter>
<parameter name="cacheProvider" required="yes">
     <description>
     You need to provider an cache provider to store its body content. for some simply use.
    Please see     @com.live.spaces.dengyin2000.tapestry.tfancomponents.components.SimpleHtmlSourceCacheProvider
    </description>
</parameter>
</component-specification>

下面的是ICacheProvider接口

 

public interface ICacheProvider {
/**
*
* @param cacheKey
* @param cacheContent
*/
public void storeCache(String cacheKey, String cacheContent);
/**
*
* @param cacheKey
* @return
*/
public String getCacheContent(String cacheKey);
/**
* This method provider to user, so that user can controll cache manaully.
* @param cacheKey
*/
public void removeCache(String cacheKey);
/**
* This method provider to user, so that user can controll cache manaully.
* Clear all caches
*
*/
public void reset();
}

ok。 再来看看Cache组件的代码。

 

public abstract class Cache extends AbstractComponent {
protected static final Log logger = LogFactory.getLog(Cache.class);
public abstract boolean getUpdateCondition();
public abstract ICacheProvider getCacheProvider();
@Override
protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
if (getUpdateCondition()){
renderComponentWithCache(writer, cycle);
}else{
if (getCacheProvider().getCacheContent(this.getIdPath()) != null){
//response cache html content.
writer.printRaw(getCacheProvider().getCacheContent(this.getIdPath()));
}else{
renderComponentWithCache(writer, cycle);
}
}

}
private void renderComponentWithCache(IMarkupWriter writer, IRequestCycle cycle) {

logger.debug("We need to refresh cache now.");
CacheWriterWrapper cacheWrapper = new CacheWriterWrapper();
super.renderBody(buildCacheMarkupWriter(cacheWrapper.getPrintWriter(), writer), cycle);
String cacheContent = cacheWrapper.getCacheContent();
logger.debug("fetched cache content, ready to put it into cache.");

getCacheProvider().storeCache(this.getIdPath(), cacheContent);
// response html content.
writer.printRaw(cacheContent);
}
private IMarkupWriter buildCacheMarkupWriter(PrintWriter writer, IMarkupWriter sourceWriter){
returnthis.getPage().getRequestCycle().getInfrastructure().getMarkupWriterSource().newMarkupWriter(writer,new ContentType(sourceWriter.getContentType()));
}
class CacheWriterWrapper{
private StringWriter sw;
private PrintWriter pw;
public CacheWriterWrapper() {
sw = new StringWriter();
pw = new PrintWriter(sw);
}

public String getCacheContent(){
return sw.getBuffer().toString();
}
public PrintWriter getPrintWriter(){
return pw;
}
}
}

主要是得到cache组件body的内容,然后把body的内容cache住,下次的话就response Cache的内容。 其实也是满简单的。

我自己还写了一个简单CacheProvider。

 

public class SimpleHtmlSourceCacheProvider implements ICacheProvider {
private Map<String, String> cache = new HashMap<String, String>();
public String getCacheContent(String cacheKey) {
return cache.get(cacheKey);
}

public void storeCache(String cacheKey, String cacheContent) {
cache.put(cacheKey, cacheContent);
}

public void removeCache(String cacheKey) {
cache.remove(cacheKey);
}

public void reset() {
cache.clear();
}
}

在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。

我在google code host上面建了一个probject地址是http://code.google.com/p/tfancomponents/ 有兴趣的同学可以看看, 这是一个maven项目。


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Page.Cache,HttpContext.Cache,HttpRuntime.Cache,Hashtable有什么区别,怎么用.
DataCache.GetCache是什么?-搜索墙
C# 数据缓存操作Cache
优化ASP.NET应用性能之Cache篇
Volley 原理分析
memcached 介绍
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服