页面整页缓存的方法【完成】

已出注解方法,移步:http://www.jfinal.com/share/344

(以下因未考虑请求参数问题,实际尚未完成...  JFinal 3.2有更好的解决方案参见CacheInterceptor )

应用场景:当魔板引擎启用setDevMode(true),而某些页面需要缓存时。(可作为页面静态化使用)

使用方法:在html中利用魔板的自定义指令进行缓存。


#CacheDirective(key, limit) 参数说明:key缓存键名, limit缓存时间(单位:秒)

#CacheDirective(key)  重载, 永久缓存

   1. config中配置自定义指令 

me.addDirective("cache", new CacheDirective());
或
me.addDirective("cache", new CacheDirective(cacheName));

   2. html中添加自定义指令#CacheDirective  #end:

#cache("testPage", 600)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    #(test)
</body>
</html>
#end

   3. 缓存前后controller中的写法比对:

//未缓存前的写法
public void test() {
    setAttr("test", "test test test !!!");
    render("test.html");
}
//缓存后的写法
public void test() {
    if ( CacheDirective.notExists("testPage") ) {
        setAttr("test", "test test test !!!");
    }
    render("test.html");
}

   直接上代码CacheDirective.java

public class CacheDirective extends Directive {
	
    private static String CACHE_NAME = "PAGE_CACHE";
	
    public CacheDirective() {
	super();
    }
	
    public CacheDirective(String cacheName) {
	super();
	CacheDirective.CACHE_NAME = cacheName;
    }
	
    @Override
    public void setExprList(ExprList exprList) {
	if ( exprList.length() != 1 || exprList.length() != 2 ) {
	    throw new ParseException("#cache directive support one/two parameter only", location);	
	}
	super.setExprList(exprList);
    }
	
    @Override
    public void exec(Env env, Scope scope, Writer writer) {
	Object[] objects = exprList.evalExprList(scope);
	String key = (String) objects[0];
	Integer limit = objects.length > 1 ? (Integer) objects[1] : null;
		
	String content = getCache(key);
	if (content == null) {
	    FastStringWriter fsw = new FastStringWriter();
	    stat.exec(env, scope, fsw);
	    content = fsw.toString();
	    putCache(key, content, limit);
	}
		
	write(writer, content);
    }
	
    @Override
    public boolean hasEnd() {
	return true;
    }
	
    public static boolean notExists(Object key) {
	return null == CacheKit.get(CACHE_NAME, key);
    }
	
    private <T> T getCache(Object key) {
	return CacheKit.get(CACHE_NAME, key);
    }
	
    private void putCache(Object key, Object value, Integer limit) {
	if ( limit == null || limit < 0 ) {
	    limit = 0;
	}
	Element element = new Element(key, value);
	element.setEternal(false);
	element.setTimeToIdle(0);//单位:秒;对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问
	element.setTimeToLive(limit);//单位:秒;对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问
	getOrAddCache(CACHE_NAME).put(element);
    }
	
    private Cache getOrAddCache(String cacheName) {
        CacheManager cacheManager = CacheKit.getCacheManager();
	Cache cache = cacheManager.getCache(cacheName);
	if ( cache == null ) {
	    cacheManager.addCacheIfAbsent(cacheName);
	    cache = cacheManager.getCache(cacheName);
	}
	return cache;
    }
	
}


评论区

JFinal

2017-06-28 17:29

相当有悟性啊,就是这么玩的。除了指令级扩展用得很好以外,还有一处亮点就是 CacheManager 动态创建 cache,连在 ehcache.xml 中的配置都省了

飞.飞

2017-06-28 17:58

@JFinal 感谢波总指导,后续改成注解方式,不需改动原来代码

爪爪

2017-06-29 08:41

就喜欢这种乐于分享的大神

海哥

2017-06-29 16:59

@JFinal putCache直接使用cachekit.put不就行了吗?为啥要自己实现?我看cacheKit里也是getOrAddCache的方式去获取cache。

飞.飞

2017-06-29 21:27

@海哥 为的是动态创建 cache 的失效时间,可以免配置。不过整个方案没考虑好请求参数的问题,目前代码最有价值的可能就是动态创建 cache 的方法了。先改下内容,免得误导大家。

爪爪

2017-06-30 11:26

@飞.飞 修改完大神记得分享 期待

我的名字就是一个字长

2017-07-03 10:32

菜鸟表示看不懂

飞.飞

2017-07-04 10:16

@JFinal @爪爪 注解方法已分享 http://www.jfinal.com/share/344

热门分享

扫码入社