package com.hundsun.jresplus.web.cache; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.runtime.directive.Directive; import org.apache.velocity.runtime.parser.node.Node; import org.apache.velocity.runtime.parser.node.SimpleNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hundsun.jresplus.common.util.StringUtil; /** * * 功能说明: 视图中用于缓存页面片段的块宏指令 * <p> * 系统版本: v1.0<br> * 开发人员: XIE xjj@hundsun.com <br> * 开发时间: 2014-7-22 <br> * 功能描述: * 视图中使用宏指令#cache(key,refresh)...#end,方式可以将指令块中的内容静态化缓存起来,缓存使用的key需要开发人员在使用是指定 * ,页面请求的视图在渲染时,如果发现存在该指令则尝试从缓存中读取静态内容,如果没有静态内容则会在渲染完成后将内容静态化并缓存,供下次使用。<br> * 宏指令的第一个参数(字符串)用于描述缓存后的唯一标示,第二个参数(布尔)用于描述是否强制刷新(强制刷新等同于不从缓存中读取)<br/> * 使用该宏指令,必须启用页面静态过滤器(PageStaticFilter) */ public class PageSnippetCacheDirect extends Directive { public static final String DIRECT_NAME = "cache"; private static final Logger logger = LoggerFactory .getLogger(PageSnippetCacheDirect.class); @Override public String getName() { return DIRECT_NAME; } @Override public int getType() { return BLOCK; } @Override public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException { String key = null; boolean refresh = false; int liveTime = getTimeToLive(context); int dleTime = getTimeToDle(context); int num = node.jjtGetNumChildren(); Node body = node.jjtGetChild(num - 1); if (num > 1) { SimpleNode keyNode = (SimpleNode) node.jjtGetChild(0); key = (String) keyNode.value(context); } if (num > 2) { SimpleNode refreshNode = (SimpleNode) node.jjtGetChild(1); Object refreshValue = refreshNode.value(context); if ("true".equals(refreshValue)) { refresh = true; } if (refreshValue instanceof Boolean) { refresh = ((Boolean) refreshValue).booleanValue(); } } if (num > 3) { SimpleNode timeNode = (SimpleNode) node.jjtGetChild(2); Object timeValue = timeNode.value(context); if (timeValue instanceof Integer) { liveTime = (Integer) timeValue; } if (timeValue instanceof String) { try { liveTime = Integer.valueOf((String) timeValue); } catch (Exception e) { logger.error( "Direct cache third arg(maxliveTime) error[key={}]", key); } } } if (num > 4) { SimpleNode timeNode = (SimpleNode) node.jjtGetChild(3); Object timeValue = timeNode.value(context); if (timeValue instanceof Integer) { dleTime = (Integer) timeValue; } if (timeValue instanceof String) { try { dleTime = Integer.valueOf((String) timeValue); } catch (Exception e) { logger.error( "Direct cache third arg(maxliveTime) error[key={}]", key); } } } String cachedContent = ""; PageStaticCache pageCache = getPaageStaticCache(context); PageImage image = pageCache == null || key == null ? null : pageCache .get(key); if (image != null) { cachedContent = image.getSnippet(); } if (refresh || StringUtil.isBlank(cachedContent)) { StringWriter sw = new StringWriter(); body.render(context, sw); cachedContent = sw.toString(); cacheContent(pageCache, key, cachedContent, liveTime, dleTime); } writer.write(cachedContent); return true; } private int getTimeToLive(InternalContextAdapter context) { Object timeObj = context.get(PageStaticFilter.PAGE_STATIC_TIME_TO_LIVE); if (timeObj != null && timeObj instanceof Integer) { return (Integer) timeObj; } return PageStaticFilter.DEF_MAX_LIVE_TIME; } private int getTimeToDle(InternalContextAdapter context) { Object timeObj = context.get(PageStaticFilter.PAGE_STATIC_TIME_TO_DLE); if (timeObj != null && timeObj instanceof Integer) { return (Integer) timeObj; } return PageStaticFilter.DEF_MAX_DLE_TIME; } private void cacheContent(PageStaticCache pageStaticCache, String key, String content, int liveTime, int dleTime) { if (StringUtil.isBlank(key) || StringUtil.isBlank(content) || pageStaticCache == null) { return; } PageImage image = new PageImage(content); image.setTimeToLiveSeconds(liveTime); image.setTimeToDleSeconds(dleTime); pageStaticCache.put(key, image); } private PageStaticCache getPaageStaticCache(InternalContextAdapter context) { Object cacheObj = context.get(PageStaticFilter.PAGE_STATIC_CACHE); if (cacheObj != null && cacheObj instanceof PageStaticCache) { return (PageStaticCache) cacheObj; } return null; } }