OSCache - CacheFilter工作原理

[color=darkblue][b]系统启动 – CacheFilter[/b][/color]
OSCache页面缓存在使用时需要在web.xml中配置CacheFilter,在容器中,Filter先于Servlet启动,下面看看CacheFilter在容器启动时,做了哪些工作:
首先需要了解OSCache的几个类:
[color=indigo]ServletCacheAdministrator[/color] -- 该类用于创建、刷新、管理缓存。
[color=indigo]Config[/color] -- 负责获取缓存配置文件,即oscache.properties。如果使用默认的构造函数,这个类会从properties文件中加载缓存配置。
[color=indigo]Cache[/color] -- 为缓存本身提供一个接口。这个类的实例会根据它的构造参数创建一个缓存。

/** 初始化Filter
* 获取web.xml文件的配置,创建ServletCacheAdministrator对象
* 获取web.xml文件中CacheFilter的初始化配置 */
public void init(FilterConfig filterConfig) {
config = filterConfig;
//初始化了ServletCacheAdministrator对象
admin = ServletCacheAdministrator.getInstance(config.getServletContext());
try {
time = Integer.parseInt(config.getInitParameter("time"));
} catch (Exception e) {
log.info("Could not get init paramter 'time', defaulting to one hour.");
}
try {
String scopeString = config.getInitParameter("scope");
if (scopeString.equals("session")) {
cacheScope = PageContext.SESSION_SCOPE;
} else if (scopeString.equals("application")) {
cacheScope = PageContext.APPLICATION_SCOPE;
} else if (scopeString.equals("request")) {
cacheScope = PageContext.REQUEST_SCOPE;
} else if (scopeString.equals("page")) {
cacheScope = PageContext.PAGE_SCOPE;
}
} catch (Exception e) {
log.info("Could not get init paramter 'scope', defaulting to 'application'");
}
}


从以上可以看出,OSCache随系统启动,仅仅做了三个步骤:
1. 创建了一个ServletCacheAdministrator对象;
2. 获取web.xml配置文件中刷新时间
3. 获取web.xml配置文件中刷新范围
在创建ServletCacheAdministrator对象时,OSCache进行了如下工作:

public static ServletCacheAdministrator getInstance(ServletContext context) {
return getInstance(context, null);
}
public static ServletCacheAdministrator getInstance(ServletContext context, Properties p) {
ServletCacheAdministrator admin = null;
admin = (ServletCacheAdministrator) context.getAttribute(CACHE_ADMINISTRATOR_KEY);
//检测Web Application中是否包含名为__oscache_admin的属性,启动时不包含,故admin为null
if (admin == null) {
admin = new ServletCacheAdministrator(context, p); //调用私有化构造函数
context.setAttribute(CACHE_ADMINISTRATOR_KEY, admin); //将admin加入__oscache_admin属性
if (log.isInfoEnabled()) {
log.info("Created new instance of ServletCacheAdministrator");
}
admin.getAppScopeCache(context);
//获取application范围缓存的方法,在这个方法中,创建并初始化了Cache和Config对象
}
return admin;
}


ServletCacheAdministrator的构造函数:

private ServletCacheAdministrator(ServletContext context, Properties p) {
super(p);
/* 父类方法做了如下工作:
* 从classpath下读取OSCache属性文件
* 通过属性文件的配置初始化缓存参数 */
config.set(HASH_KEY_CONTEXT_TMPDIR,
context.getAttribute("javax.servlet.context.tempdir"));
//设置context.tempdir = D:\Tomcat6\work\Catalina\localhost\OSCacheWebTest
flushTimes = new HashMap();
initHostDomainInKey(); //私有变量boolean useHostDomainInKey = null
}

通过以上方法,在ServletContext上下文中,设置了如下属性:
context.setAttribute(CACHE_ADMINISTRATOR_KEY, admin);
将创建的ServletCacheAdministrator对象放入名为__oscache_admin的属性
context.setAttribute(getCacheKey(), cache);
将创建的Cache对象放入名为__oscache_cache的属性

[b][color=darkblue]缓存页面首次打开与刷新 – doFilter[/color][/b]
首先需要了解OSCache的几个类:
ResponseContent:在缓存中用byte数组形式保留servlet响应对象。

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
//产生一个缓存目录的key:/OSCacheWebTest/cache1.jsp_GET_
String key = admin.generateEntryKey(null, httpRequest, cacheScope);
//获取指定范围的缓存
Cache cache = admin.getCache(httpRequest, cacheScope);
以上语句进行了如下工作:
1. 定位缓存范围:session还是application(这里在配置文件中设置的是session)
2. 检查HttpSession对象中名为__oscache_cache的属性是否为空
如果为空(第一次打开页面):创建一个缓存,将其放入HttpSession对象的__oscache_cache属性中
不为空(刷新页面):直接从HttpSession对象中获取__oscache_cache属性的值,即直接获取缓存
try {
//通过缓存中的key得到相应的对象
ResponseContent respContent = (ResponseContent) cache.getFromCache(key, time);
respContent.writeTo(response); //将缓存数据写入到ServletResponse
} catch (NeedsRefreshException nre) {
………………
} finally {
………………
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章