有许多页面的一部分或者这个页面是很少更新的,他们通常是由外部文件来生成这个部分。所以我们可以把这部分内容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>
这里有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.
- <!--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接口:
- 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();
- }
ok。 再来看看Cache组件的代码。
- 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。
我在google code host上面建了一个probject地址是http://code.google.com/p/tfancomponents/ 有兴趣的同学可以看看, 这是一个maven项目。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12467/viewspace-148272/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12467/viewspace-148272/