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; } }