原创 Tapestry的Cache组件

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

说干就干,先在头脑中想好要怎样使用cache(页面上的布局)。ok。 我想好了。
xml 代码
 
  1. <span jwcid="@Cache" cacheProvider="ognl:cacheProvider" updateCondition="ognl:needUpdate">  
  2.   
  3.     //Cache body, which is the content you want to cache.  
  4.   
  5. <!---->span>  

这里有2个参数,updateCondition 当为true时,我们就绕过cache, cacheProvider 我把他定义为一个接口,这样用户可以把cache存在任何地方。而且提供这样的一个接口,用户可以更好的操作cache。先看看jwc对cache组件的定义。
xml 代码
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2.   "-//Apache Software Foundation//Tapestry Specification 4.0//EN"   
  3.   "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">  
  4.   
  5. <component-specification allow-body="yes" allow-informal-parameters="no" class="com.live.spaces.dengyin2000.tapestry.tfancomponents.components.Cache">  
  6.     <description>  
  7.         Cache component, this component can inclue any content as its body, and cache its body.  
  8.         This is useful in rarely updated content.  
  9.     <!---->description>  
  10.     <parameter name="updateCondition" required="no" default-value="false">  
  11.         <description>  
  12.             The flag that need to refresh cache, it would casue tapestry render not use the cache.  
  13.         <!---->description>  
  14.     <!---->parameter>  
  15.     <parameter name="cacheProvider" required="yes">  
  16.         <description>  
  17.             You need to provider an cache provider to store its body content. for some simply use.  
  18.             Please see @com.live.spaces.dengyin2000.tapestry.tfancomponents.components.SimpleHtmlSourceCacheProvider  
  19.         <!---->description>  
  20.     <!---->parameter>  
  21. <!---->component-specification>  

下面的是ICacheProvider接口:
java 代码
 
  1. package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;  
  2. /** 
  3.  * @author Denny - [email protected] 
  4.  * @since 2006-12-21 
  5.  */  
  6. public interface ICacheProvider {  
  7.       
  8.     /** 
  9.      *  
  10.      * @param cacheKey 
  11.      * @param cacheContent 
  12.      */  
  13.     public void storeCache(String cacheKey, String cacheContent);  
  14.       
  15.     /** 
  16.      *  
  17.      * @param cacheKey 
  18.      * @return 
  19.      */  
  20.     public String getCacheContent(String cacheKey);   
  21.       
  22.     /** 
  23.      * This method provider to user, so that user can controll cache manaully. 
  24.      * @param cacheKey 
  25.      */  
  26.     public void removeCache(String cacheKey);  
  27.       
  28.     /** 
  29.      * This method provider to user, so that user can controll cache manaully. 
  30.      * Clear all caches 
  31.      * 
  32.      */  
  33.     public void reset();  
  34.       
  35. }  

ok。 再来看看Cache组件的代码。
java 代码
 
  1. package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;  
  2.   
  3. import java.io.PrintWriter;  
  4. import java.io.StringWriter;  
  5.   
  6. import org.apache.commons.logging.Log;  
  7. import org.apache.commons.logging.LogFactory;  
  8. import org.apache.tapestry.AbstractComponent;  
  9. import org.apache.tapestry.IMarkupWriter;  
  10. import org.apache.tapestry.IRequestCycle;  
  11. import org.apache.tapestry.util.ContentType;  
  12.   
  13. /** 
  14.  * @author Denny deng 
  15.  * 
  16.  */  
  17. public abstract class Cache extends AbstractComponent {  
  18.       
  19.     protected static final Log logger = LogFactory.getLog(Cache.class);  
  20.       
  21.     public abstract boolean getUpdateCondition();  
  22.       
  23.     public abstract ICacheProvider getCacheProvider();  
  24.       
  25.     @Override  
  26.     protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {  
  27.           
  28.         if (getUpdateCondition()){  
  29.             renderComponentWithCache(writer, cycle);  
  30.         }else{  
  31.             if (getCacheProvider().getCacheContent(this.getIdPath()) != null){  
  32.                   
  33.                 //response cache html content.  
  34.                 writer.printRaw(getCacheProvider().getCacheContent(this.getIdPath()));  
  35.             }else{  
  36.                 renderComponentWithCache(writer, cycle);  
  37.             }  
  38.         }  
  39.   
  40.     }  
  41.       
  42.     private void renderComponentWithCache(IMarkupWriter writer, IRequestCycle cycle) {  
  43.   
  44.         logger.debug("We need to refresh cache now.");  
  45.         CacheWriterWrapper cacheWrapper = new CacheWriterWrapper();  
  46.         super.renderBody(buildCacheMarkupWriter(cacheWrapper.getPrintWriter(), writer), cycle);  
  47.         String cacheContent = cacheWrapper.getCacheContent();  
  48.         logger.debug("fetched cache content, ready to put it into cache.");  
  49.   
  50.         getCacheProvider().storeCache(this.getIdPath(), cacheContent);  
  51.           
  52.         // response html content.  
  53.         writer.printRaw(cacheContent);  
  54.     }  
  55.       
  56.     private IMarkupWriter buildCacheMarkupWriter(PrintWriter writer, IMarkupWriter sourceWriter){  
  57.         return this.getPage().getRequestCycle().getInfrastructure().getMarkupWriterSource().newMarkupWriter(writer, new ContentType(sourceWriter.getContentType()));  
  58.     }  
  59.       
  60.     class CacheWriterWrapper{  
  61.         private StringWriter sw;  
  62.         private PrintWriter pw;   
  63.         public CacheWriterWrapper() {  
  64.             sw = new StringWriter();  
  65.             pw = new PrintWriter(sw);  
  66.         }  
  67.   
  68.         public String getCacheContent(){  
  69.             return sw.getBuffer().toString();  
  70.         }  
  71.           
  72.         public PrintWriter getPrintWriter(){  
  73.             return pw;  
  74.         }  
  75.     }  
  76. }  

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

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

java 代码
  1. package com.live.spaces.dengyin2000.tapestry.tfancomponents.components;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. /** 
  7.  * @author Denny - [email protected] 
  8.  * @since 2006-12-21 
  9.  */  
  10. public class SimpleHtmlSourceCacheProvider implements ICacheProvider {  
  11.       
  12.     private Mapnew HashMap
  13.       
  14.     public String getCacheContent(String cacheKey) {  
  15.         return cache.get(cacheKey);  
  16.     }  
  17.   
  18.     public void storeCache(String cacheKey, String cacheContent) {  
  19.         cache.put(cacheKey, cacheContent);  
  20.     }  
  21.   
  22.     public void removeCache(String cacheKey) {  
  23.         cache.remove(cacheKey);  
  24.     }  
  25.   
  26.     public void reset() {  
  27.         cache.clear();  
  28.     }  
  29. }  
在使用中你可以把CacheProvider放到Global或者Visit对象中。注意要使用同一个CacheProvider。

 

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

你可能感兴趣的:(apache,maven,cache,tapestry,Gmail)