com.jfinal.plugin.ehcache.CacheInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfinal Show documentation
Show all versions of jfinal Show documentation
JFinal is a simple, light, rapid,independent, extensible Java WEB + ORM framework. The feature of JFinal looks like ruby on rails especially ActiveRecord.
/**
* Copyright (c) 2011-2023, James Zhan 詹波 ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.plugin.ehcache;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.HttpServletRequest;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.render.Render;
/**
* CacheInterceptor.
*/
public class CacheInterceptor implements Interceptor {
private static final String renderKey = "_renderKey";
private static ConcurrentHashMap lockMap = new ConcurrentHashMap(512);
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;
}
final public void intercept(Invocation inv) {
Controller controller = inv.getController();
String cacheName = buildCacheName(inv, controller);
String cacheKey = buildCacheKey(inv, controller);
Map cacheData = CacheKit.get(cacheName, cacheKey);
if (cacheData == null) {
Lock lock = getLock(cacheName);
lock.lock(); // prevent cache snowslide
try {
cacheData = CacheKit.get(cacheName, cacheKey);
if (cacheData == null) {
inv.invoke();
cacheAction(cacheName, cacheKey, controller);
return ;
}
}
finally {
lock.unlock();
}
}
useCacheDataAndRender(cacheData, controller);
}
// TODO 考虑与 EvictInterceptor 一样强制使用 @CacheName
protected String buildCacheName(Invocation inv, Controller controller) {
CacheName cacheName = inv.getMethod().getAnnotation(CacheName.class);
if (cacheName != null)
return cacheName.value();
cacheName = controller.getClass().getAnnotation(CacheName.class);
return (cacheName != null) ? cacheName.value() : inv.getActionKey();
}
protected String buildCacheKey(Invocation inv, Controller controller) {
StringBuilder sb = new StringBuilder(inv.getActionKey());
String urlPara = controller.getPara();
if (urlPara != null)
sb.append('/').append(urlPara);
String queryString = controller.getRequest().getQueryString();
if (queryString != null)
sb.append('?').append(queryString);
return sb.toString();
}
/**
* 通过继承 CacheInterceptor 并覆盖此方法支持更多类型的 Render
*/
protected RenderInfo createRenderInfo(Render render) {
return new RenderInfo(render);
}
protected void cacheAction(String cacheName, String cacheKey, Controller controller) {
HttpServletRequest request = controller.getRequest();
Map cacheData = new HashMap();
for (Enumeration names=request.getAttributeNames(); names.hasMoreElements();) {
String name = names.nextElement();
cacheData.put(name, request.getAttribute(name));
}
Render render = controller.getRender();
if (render != null) {
cacheData.put(renderKey, createRenderInfo(render)); // cache RenderInfo
}
CacheKit.put(cacheName, cacheKey, cacheData);
}
protected void useCacheDataAndRender(Map cacheData, Controller controller) {
HttpServletRequest request = controller.getRequest();
Set> set = cacheData.entrySet();
for (Iterator> it=set.iterator(); it.hasNext();) {
Entry entry = it.next();
request.setAttribute(entry.getKey(), entry.getValue());
}
request.removeAttribute(renderKey);
RenderInfo renderInfo = (RenderInfo)cacheData.get(renderKey);
if (renderInfo != null) {
controller.render(renderInfo.createRender()); // set render from cacheData
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy