1、OSCache是什么?
OSCache标记库由OpenSymphony设计,它是一种开创性的缓存方案,它提供了在现有JSP页面之内实现内存缓存的功能。OSCache是个一个被广泛采用的高性能的J2EE缓存框架,OSCache还能应用于任何Java应用程序的普通的缓存解决方案。
2、OSCache的特点
(1) 缓存任何对象:你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。
(2) 拥有全面的API:OSCache API允许你通过编程的方式来控制所有的OSCache特性。
(3) 永久缓存:缓存能被配置写入硬盘,因此允许在应用服务器的多次生命周期间缓存创建开销昂贵的数据。
(4) 支持集群:集群缓存数据能被单个的进行参数配置,不需要修改代码。
(5) 缓存过期:你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不能满足需要时)。
3、OSCache的安装与配置
4、有关“用OSCache进行缓存对象”的研究
这个是我今天要说的东西。网上对于OSCache缓存Web页面很多说明和例子,但对于缓存对象方面说得不多,我就把自已写得一些东西放出来,让大家看一看是怎样缓存对象的!
我基于GeneralCacheAdministrator类来写的BaseCache类
Java代码
package com.klstudio.cache;
import java.util.Date;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;
public class BaseCache extends GeneralCacheAdministrator {
//过期时间(单位为秒);
private int refreshPeriod;
//关键字前缀字符;
private String keyPrefix;
private static final long serialVersionUID = -4397192926052141162L;
public BaseCache(String keyPrefix,int refreshPeriod){
super();
this.keyPrefix = keyPrefix;
this.refreshPeriod = refreshPeriod;
}
//添加被缓存的对象;
public void put(String key,Object value){
this.putInCache(this.keyPrefix+"_"+key,value);
}
//删除被缓存的对象;
public void remove(String key){
this.flushEntry(this.keyPrefix+"_"+key);
}
//删除所有被缓存的对象;
public void removeAll(Date date){
this.flushAll(date);
}
public void removeAll(){
this.flushAll();
}
//获取被缓存的对象;
public Object get(String key) throws Exception{
try{
return this.getFromCache(this.keyPrefix+"_"+key,this.refreshPeriod);
} catch (NeedsRefreshException e) {
this.cancelUpdate(this.keyPrefix+"_"+key);
throw e;
}
}
}
通过CacheManager类来看怎样缓存对象的,这个类中所用的News只是具体功能的类,我就不贴出来了,你可以自己写一个!
Java代码
package com.klstudio;
import com.klstudio.News;
import com.klstudio.cache.BaseCache;
public class CacheManager {
private BaseCache newsCache;
private static CacheManager instance;
private static Object lock = new Object();
public CacheManager() {
//这个根据配置文件来,初始BaseCache而已;
newsCache = new BaseCache("news",1800);
}
public static CacheManager getInstance(){
if (instance == null){
synchronized( lock ){
if (instance == null){
instance = new CacheManager();
}
}
}
return instance;
}
public void putNews(News news) {
// TODO 自动生成方法存根
newsCache.put(news.getID(),news);
}
public void removeNews(String newsID) {
// TODO 自动生成方法存根
newsCache.remove(newsID);
}
public News getNews(String newsID) {
// TODO 自动生成方法存根
try {
return (News) newsCache.get(newsID);
} catch (Exception e) {
// TODO 自动生成 catch 块
System.out.println("getNews>>newsID["+newsID+"]>>"+e.getMessage());
News news = new News(newsID);
this.putNews(news);
return news;
}
}
public void removeAllNews() {
// TODO 自动生成方法存根
newsCache.removeAll();
}
}
一、缓存整个页面
在OSCache组件中提供了一个CacheFilter用于实现页面级的缓存,主要用于对web应用中的某些动态页面进行缓存,尤其是那些需要生成PDF格式文件/报表、图片文件等的页面,不仅减少了数据库的交互、减少数据库服务器的压力,而且对于减少web服务器的性能消耗有很显著的效果。
这种功能的实现是通过在web.xml中进行配置来决定缓存哪一个或者一组页面,而且还可以设置缓存的相关属性,这种基于配置文件的实现方式对于J2EE来说应该是一种标准的实现方式了。
[注] 只有客户访问时返回http头信息中代码为200(也就是访问已经成功)的页面信息才能够被缓存。
修改web.xml,增加如下内容,确定对/testContent.jsp页面进行缓存。
<filter>
<filter-name>CacheFilter</filter-name>
<filter-class>com.opensymphony.oscache.web.filter.CacheFilter</filter-class>
<init-param>
<param-name>time</param-name>
<param-value>600</param-value>
</init-param>
<init-param>
<param-name>scope</param-name>
<param-value>session</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CacheFilter</filter-name>
<!-对所有jsp页面内容进行缓存-->
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
在页面级缓存的情况下,可以通过设置CacheFilter的初始属性来决定缓存的一些特性:time属性设置缓存的时间段,默认为3600秒,可以根据自己的需要只有的设置,而scope属性设置,默认为application,可选项包括application、session。
二、缓存页面的部分
1、OSCache标签库配置
(1) 从src\webapp\WEB-INF\classes或etc目录取得soscache.tld文件,放在CLASSPATH下(src根目录或发布环境的/WEB-INF/classes 目录)。该文件定义了OSCache的定义。
(2) 将下列代码加入web.xml文件中:
<taglib>
<taglib-uri>oscache</taglib-uri>
<taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>
</taglib>
2、cache标签
这是OSCache提供的标签库中最重要的一个标签,包括在标签中的内容将应用缓存机制进行处理,处理的方式将取决于编程者对cache标签属性的设置。
第一次请求到达时,标签中的内容被处理并且缓存起来,当下一个请求到达时,缓存系统会检查这部分内容的缓存是否已经失效,主要是以下几项:
(1)缓存时间超过了cache标签设置的time或者duration属性规定的超时时间
(2)cron属性规定的时间比缓存信息的开始时间更晚
(3)标签中缓存的内容在缓存后又被重新刷新过
(4)其他缓存超期设定
如果符合上面四项中的任何一项,被缓存的内容视为已经失效,这时被缓存的内容将被重新处理并且返回处理过后的信息,如果被缓存的内容没有失效,那么返回给用户的将是缓存中的信息。
cache标签的常用属性说明:
key
标识缓存内容的关键词。在指定的作用范围内必须是唯一的。默认的key是被访问页面的URI和后面的请求字符串。可以在同一个页面中使用很多cache标签而不指定他的key属性,这种情况下系统使用该页面的URI和后面的请求字符串,另外再自动给这些key增加一个索引值来区分这些缓存内容。但是不推荐采用这样的方式。
scope
缓存发生作用的范围,可以是application或者session。默认为application。
time
缓存内容的时间段,单位是秒,默认是3600秒,也就是一个小时,如果设定一个负值,那么这部分被缓存的内容将永远不过期。
duration
指定缓存内容失效的时间,是相对time的另一个选择,可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等。
cron
指定缓存内容失效表达式,见“Cron表达式基本语法”。
refresh
false 或者true。如果refresh属性设置为true,不管其他的属性是否符合条件,这部分被缓存的内容都将被更新,这给编程者一种选择,决定什么时候必须刷新。
mode
如果不希望被缓存的内容增加到给用户的响应中,可以设置mode属性为"silent"。此时被缓存的部分不在页面上显示,而其它任意的mode属性值都会将缓存的部分显示到页面上。
groups
指定当前cache标签所属的组,可使用“,”分割组名。这样就可以对缓存项进行分组了。如果缓存项依赖于应用的其它部分或其它数据,分组就有了用武之地——当这种依赖改变时(刷新相关的组),这个组的所有缓存项都将过期。
language
使用ISO-639定义的语言码来发布不同的缓存内容(under an otherwise identical key)。要在一个多语言网站上同一段JSP代码不同用户的参数提供不同的语言时,这个属性会很有用。
refreshpolicyclass
指定自定义的刷新策略类的全限定类名。这个类继承自com.opensymphony.oscache.web.WebEntryRefreshPolicy
refreshpolicyparam
指定任意需要传给refreshpolicyclass的参数。如果没有指定refreshpolicyclass,则这个值不起作用。
这些属性可以单独使用,也可以根据需要组合使用。
3、Cron表达式基本语法
通过Cron表达式我们可以很灵活的设置缓存的失效时间,Cron表达式包括5个字段分别为Minute,Hour, DOM(Day Of Month), Month,DOW(Day Of Week)。他们顺序地对应了5个位置。当某个位置上的值为*时,表示该位置上的任意时间。另外还提供了指定时间的操作符号"-",",","/",他们分别表示一段时间范围,具体的时间,以及递增的时间段。下面是几个例子说明一下Cron表达式的基本应用:
(1) "10/20 * * * *" :因是第一个位置,并且是一个递增的表达式,所以表达式指定的是每个小时的第10分钟,第30分钟,第50分钟缓存内容失效。
(2) "* 8-18/4 * * *" :指定每天早上8点到晚上6点之间,每4个小时缓存内容失效。 等同于"* 8,12,16 * * *"。
(3) "* * * * 1-5":表示每个星期一到星期五内容失效。
4、Cache标签实例分析
(1) 最简单的cache标签用法。使用默认的关键字来标识cache内容,超时时间是默认的3600秒。 <oscache:cache>
<%
//自己的JSP代码内容
%>
</oscache:cache>
(2) 用自己指定的字符串标识缓存内容,并且设定作用范围为session。
<oscache:cache key="foobar" scope="session">
<%
//自己的JSP代码内容
%>
</oscache:cache>
(3) 动态设定key值,使用自己指定的time属性设定缓存内容的超时时间,使用动态refresh值决定是否强制内容刷新。因为OSCache使用key值来标识缓存内容,使用相同的key值将会被认为使用相同的的缓存内容,所以使用动态的key值可以自由的根据不同的角色、不同的要求决定使用不同的缓存内容。
<oscache:cache key="<%= product.getId() %>" time="1800" refresh="<%= needRefresh %>">
<%
//自己的JSP代码内容
%>
</oscache:cache>
(4) 设置time属性为负数使缓存内容永不过期
<oscache:cache time="-1">
<%
//自己的JSP代码内容
%>
</oscache:cache>
(5) 使用duration属性设置超期时间
<oscache:cache duration='PT5M'>
<%
//自己的JSP代码内容
%>
</oscache:cache>
(6) 使用mode属性使被缓存的内容不加入给客户的响应中
<oscache:cache mode='silent'>
<%
//自己的JSP代码内容
%>
</oscache:cache>
5、flush标签
这个标签用于在运行时刷新缓存。只有运行flush标签后再次访问相关缓存项时才执行刷新。
属性说明:
scope[all]
指定要刷新的范围。可选的值是"application", "session" 和 nul。null(到底是null量还是all呀)值指定刷新所有的缓存(是指使用cache标签的缓存)。
key
当指定了scope和key值时,刷新唯一的缓存项。当这个缓存项下次被访问时将被刷新。只指定一个key值而没有指定scope不起作用。
group
指定一个组时将刷新所有这个组中的缓存项。只指定一个group值而没有指定scope不起作用。
pattern
任意包含pattern属性指定的值的缓存项都将被刷新。只指定一个pattern值而没有指定scope不起作用。 (注意:OSCache项目组已经不赞成使用pattern这个属性赖刷新缓存,二是鼓励使用具有更好的灵活性和性能的group属性来代替)
language
使用ISO-639定义的语言码来发布不同的缓存内容(under an otherwise identical key)。要在一个多语言网站上同一段JSP代码不同用户的参数提供不同的语言时,这个属性会很有用。
6、usecached标签
<usecached />:必须嵌套在<cache>标签中。
属性说明:
use
告诉所在的<cache>标签是否使用已经缓存的内容(缺省为true,使用缓存的内容)。可以使用这个标签来控制缓存。比如使用<frush>标签刷新某个key的缓存,但可以在必要的地方即使这样的强制刷新也仍然使用缓存内容而不刷新。
示例代码如下:
<oscache:cache>
<% try { %>
... some jsp content ...
<% } catch (Exception e) { %>
<cache:usecached />
<% } %>
</oscache:cache>
7、addgroup标签
<addgroup />:必须嵌套在<cache>标签中。It allows groups to be dynamically added to a cached block. It is useful when the group(s) a cached block should belong to are unknown until the block is actually rendered. As each group is 'discovered', this tag can be used to add the group to the block's group list.
属性说明:
group- req
The name of the group to add the enclosing cache block to.
示例代码如下:
<oscache:cache key="test1">
<oscache:addgroup group="group1" />
... some jsp content ...
<oscache:addgroup group="group2" />
... some more jsp content ...
</oscache:cache>
8、使用标签的特殊说明
(1) 标签的属性值如果动态生成,则需要先把动态生成的值赋予一个变量,再使用JSP 表达式把动态值赋予对应的属性。
<!--正确的写法:-->
<%
String keyValue = (String)request.getAttribute("keyValue");
if(keyValue == null)
keyValue = "";
%>
<oscache:cache refresh='<%=keyValue%>'>……</ oscache:cache >
<!--不正确的写法:-->
<oscache:cache refresh='<%=(String)request.getAttribute("keyValue")%>'>
<!-属性的值此时为字符串“<%=(String)request.getAttribute("keyValue")%>”--->
</ oscache:cache >
(2) 标签的属性值对boolean是强类型的,比如cache的refresh属性要求为true或false,示例如下:
<!--正确的写法:-->
<oscache:cache refresh='true'>……</ oscache:cache >
<!--正确的写法:-->
<%
String needRefresh = (String)application.getAttribute("needRefresh");
if(needRefresh == null)
needRefresh = "false";
boolean t_f = Boolean.valueOf(needRefresh).booleanValue();
%>
<oscache:cache refresh='<%=t_f %>'>……</ oscache:cache >
<!--不正确的写法:-->
<oscache:cache refresh='<%= needRefresh %>'>……</ oscache:cache >