1、JFinalConfig configInterceptor方法最后加入:
me.add(new ViewCacheInterceptor());
2、在需要缓存页面的Controller方法中进行注解:
/**
* @param view 与render(view)中的view相同
* @param live 缓存存活时间(单位:秒),对应EhCache的TimeToLive
* @param idle 缓存空闲时间(单位:秒),对应EhCache的TimeToIdle
*/
@ViewCache(view = "index.html", live = 60, idle = 0)
public void index() {
int pageNumber = getParaToInt("p", 1);
int pageSize = getParaToInt("s", 10);
Page<Role> page = srv.getPage(pageNumber, pageSize);
setAttr("page", page);
render("index.html");
}3、清除缓存方法(不提供,自行处理)
缓存命名规则如下:
cacheName: controller.getClass().getName()
cacheKey: methodName + ":" + urlParas
如清除以上第2步的index方法缓存,可根据cacheName遍历对“index”开头的cacheKey进行清除即可。
4、最后上代码
ViewCache.class代码:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ViewCache {
String view();
int live();
int idle();
}ViewCacheInterceptor.class代码:
public class ViewCacheInterceptor implements Interceptor {
private static ConcurrentHashMap<String, ReentrantLock> lockMap = new ConcurrentHashMap<String, ReentrantLock>();
@Override
public void intercept(Invocation inv) {
ViewCache viewCache = inv.getMethod().getAnnotation(ViewCache.class);
if ( viewCache != null ) {
Controller c = inv.getController();
String cacheName = c.getClass().getName();
String cacheKey = getCacheKey(c, inv.getMethodName());
String cacheData = CacheKit.get(cacheName, cacheKey);
if ( cacheData != null ) {
c.renderHtml(cacheData);
} else {
inv.invoke();
buildCache(inv, c, cacheName, cacheKey, viewCache);
}
return;
}
inv.invoke();
}
private ReentrantLock getLock(String key) {
ReentrantLock lock = lockMap.get(key);
if ( lock != null ) {
return lock;
}
lock = new ReentrantLock();
ReentrantLock previousLock = lockMap.putIfAbsent(key, lock);
return previousLock == null ? lock : previousLock;
}
private String getCacheKey(Controller c, String methodName) {
StringBuilder sb = new StringBuilder(c.getClass().getName());
String urlPara = c.getPara();
if ( urlPara != null ) {
sb.append('/').append(urlPara);
}
String queryString = c.getRequest().getQueryString();
if ( queryString != null ) {
sb.append('?').append(queryString);
}
return sb.length() > 0 ? methodName + ":" + sb.toString() : methodName;
}
private void buildCache(Invocation inv, Controller c, String cacheName, String cacheKey, ViewCache viewCache) {
Lock lock = getLock(cacheName);
lock.lock(); // prevent cache snowslide
try {
Object cacheData = CacheKit.get(cacheName, cacheKey);
if ( cacheData == null ) {
Map<String, Object> map = new HashMap<String, Object>();
for (Enumeration<String> names = c.getRequest().getAttributeNames(); names.hasMoreElements();) {
String name = names.nextElement();
map.put(name, c.getRequest().getAttribute(name));
}
String view = viewCache.view();
if (view != null && view.length() > 0 && view.charAt(0) != '/') {
view = inv.getViewPath() + view;
}
putCache(cacheName, cacheKey, c.renderToString(view, map), viewCache.live(), viewCache.idle());
}
} finally {
lock.unlock();
}
}
private void putCache(String cacheName, Object key, Object value, int live, int idle) {
Element element = new Element(key, value);
element.setEternal(false);
element.setTimeToLive(live);//单位:秒;对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问
element.setTimeToIdle(idle);//单位:秒;对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问
getOrAddCache(cacheName).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;
}
}