技术开发 频道

Tapestry的Cache组件


IT168技术文档】 
    有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容cache住,当有新的请求时,我们就response cache,这样可以减少服务器的负担,还可以提高性能。其中oscache已经可以实现页面的cache和页面部分cache。oscache使用jsp tags来实现局部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-->span>
    这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。
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>
    下面的是ICacheProvider接口:
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组件的代码。
//---------------------------------------------------------------------------- /** * * @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; } } }
    主要是得到cache组件body的内容,然后把body的内容cache住,下次的话就response Cache的内容。 其实也是满简单的。 我自己还写了一个简单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(); } }
    在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。
0
相关文章