Tapestry的Cache组件
【IT168技术文档】
有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容cache住,当有新的请求时,我们就response cache,这样可以减少服务器的负担,还可以提高性能。其中oscache已经可以实现页面的cache和页面部分cache。oscache使用jsp tags来实现局部cache的。拿到Tapestry中肯定是行不通的。在同事的提醒下,想到写这个Tapestry的cache组件来达到重用的目的。
说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。
这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。<span jwcid="@Cache" cacheProvider="ognl:cacheProvider" updateCondition="ognl:needUpdate">
![]()
//Cache body, which is the content you want to cache.
![]()
<!--</span-->span>
下面的是ICacheProvider接口:xml version="1.0" encoding="UTF-8"?>
![]()
"-//Apache Software Foundation//Tapestry Specification 4.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
![]()
<component-specification allow-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.
<!--</span-->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.<!--</span-->description>
<!--</span-->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<!--</span-->description>
<!--</span-->parameter>
<!--</span-->component-specification>
package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
/**//**
* @author Denny - deng.yin@gmail.com
* @since 2006-12-21
*/
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();
![]()
}
【IT168技术文档】
再来看看Cache组件的代码。
主要是得到cache组件body的内容,然后把body的内容cache住,下次的话就response Cache的内容。 其实也是满简单的。 我自己还写了一个简单CacheProvider。//----------------------------------------------------------------------------
/**//**
*
* @author Copyright (c) 2006 - 2008 by Monitor110, Inc.
* All Rights Reserved.
*/
//----------------------------------------------------------------------------
package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
![]()
import java.io.PrintWriter;
import java.io.StringWriter;
![]()
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.util.ContentType;
![]()
/**//**
* @author Denny deng
*
*/
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)...{return this.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;
}
}
}
在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;
![]()
import java.util.HashMap;
import java.util.Map;
![]()
/**//**
* @author Denny - deng.yin@gmail.com
* @since 2006-12-21
*/
public class SimpleHtmlSourceCacheProvider implements ICacheProvider ...{
![]()
private Mapnew HashMap
![]()
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();
}
}
0
相关文章
