最近一个项目用到OsCache的页面片段缓存,google了一下居然没有找到OsCache的监控工具(list all keys from cache),于是大略读了一下OSCache-2.4.1的源码,发现Cache.java类的cacheMap定义成了私有变量,如下:
/**
* The actual cache map. This is where the cached objects are held.
*/
private AbstractConcurrentReadCache cacheMap = null;
所以只能用反射机制暴力破解了(按照Sun公司的JVM规范是许可的^_^),主要代码如下:
1) OsCacheUtil.java
/**
* 通过反射机制获取Cache私有成员变量cacheMap, 2012/10/8, by jeffsang
* @return
*/
public static AbstractConcurrentReadCache getCacheMap(ServletContext ctx) {
//获取Cache对象实例
Cache cache = ServletCacheAdministrator.getInstance(ctx).getAppScopeCache(ctx);
//通过反射机制获取Cache私有成员变量cacheMap
AbstractConcurrentReadCache cacheMap = null;
try {
Field field = Cache.class.getDeclaredField("cacheMap" );
field.setAccessible( true);
cacheMap = (AbstractConcurrentReadCache) field.get(cache);
field.setAccessible( false);
}
catch (Exception e) {
log.warn( "can't acquire oscache Cache.cacheMap! " , e);
}
return cacheMap;
}
/**
* 获取ServletCache的全部Application Scope的cache, 2012/10/8, by jeffsang
* @return
*/
public static Map getAppScopeCaches(ServletContext ctx) {
Map map = new HashMap();
//获取Cache对象实例
Cache cache = ServletCacheAdministrator.getInstance(ctx).getAppScopeCache(ctx);
//通过反射机制获取Cache私有成员变量cacheMap
AbstractConcurrentReadCache cacheMap = getCacheMap(ctx);
//返回包含在cacheMap中的Map关系的 Set视图。
@SuppressWarnings("unchecked")
Set> setEntry = cacheMap.entrySet();
//使用Iterator遍历器
//Iterator> it = cacheMap.entrySet().iterator();
//使用for遍历cacheMap中的entrySet
for (Map.Entry entry : setEntry) {
String key = entry.getKey();
Object value = cache.getFromCache(key);
//以下方法只能得到CacheEntry对象实例Id
//Object value = entry.getValue();
map.put(key, value);
}
return map;
}
2) oscache_list.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="java.util.*" %>
<%@ page import="com.lasun.util.OsCacheUtil" %>
<%
Map<String, Object> map = OsCacheUtil.getAppScopeCaches(request.getServletContext());
request.setAttribute("map", map);
%>
<table border="1">
<tr>
<th>No</th>
<th>Key</th>
<th>Value</th>
</tr>
<c:forEach var="entry" items="${map}" varStatus="status">
<tr>
<td>${status.index+1}</td>
<td>${entry.key}</td>
<td>${entry.value}</td>
</tr>
</c:forEach>
</table>
小结:
本例子只实现ServletCache中的Application Scop的cache list功能;通过Listener或持久化也能实现监控。