一、基本概述
OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案。
OSCache的特点:
1. 缓存任意对象:可以不受限制的缓存JSP的一部分或是Http请求,任何的Java对象都可以被缓存。
2.全面的API:通过API可以完完全全的控制OSCache的任何特性。
3.持久缓存:我们可以把认为重要的数据缓存到硬盘上。
4.支持集群:集群缓存数据能被单个的进行参数配置,不需要修改代码。
5.缓存记录的过期:你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
二、作用以及优缺点
可以使用内存、硬盘空间、同时使用内存和硬盘或者提供自己的其他资源(需要自己提供适配器)作为缓存区。使用内存作为缓存区将可以提供更好的性能
使用硬盘作为缓存区可以在服务器重起后迅速恢复缓存内容
同时使用内存和硬盘作为缓存区则可以减少对内存的占用
OSCache可解决动态网站问题
1. 缓存动态内容:其实我们的动态网页上一般只有一部分是动态的(表头,表尾一般是不变的),如果我们缓存整个网页显然不成,因为有部分是随着请求有可能变的。OSCache提供的方式是允许我们只缓存一部分网页。
2. 缓存2进制内容:产生的图片和PDF文件在服务器加载的时候非常的耗时。OSCache解决这个问题是通过一个Servlet2.3的缓存过滤功能,然后能够缓存任意的URI(比如一个完整的页面或者是一个产生的图片/PDF文件)
3. 容错:有这种情况或许我们会遇到,就是当一个动态的网页出现错误。即便我们的页面有95%都加载完毕,但就是由于这个错误,整个页面就会
返回错误的提示或页面。OSCache允许我们提供出现错误时的缓存内容,如果出现就适时的提示出来了。
三、OSCache运行环境
如果用到OSCache Tag Library的话,需要Servlet2.3和JSP1.2的支持。如果是直接用OSCache API的话那么就不需要Servlet容器的支持。
目前可以正常运行的Web容器:
1. OrionServer(版本1.4.0和更高)
2. JRun(3.0或更好)
3. WebLogic(8.1或以上)
4.Websphere(5.0或以上)
5. Resin(1.2.3或以上)
6. TomCat(4.0或以上)
7. iPlanet(6.0或以上)
用到缓存过滤需要Servlet2.3支持.目前知道的可以工作在OrionServer,WebLogic,Tomcat上.
OSCache需要Java的版本至少是java 1.4.
四.OSCache的安装
1解压oscache-2.4.1-full后发现他下面有如下文件:
2.把oscache-2.4.1.jar放到/WEB-INF/lib下.
3.要确保commons-logging.jar也在环境变量中.一般情况下他也放在/WEB-INF/lib下.
4. 把/etc/oscache.properties放入/WEB-INF/classes下
果用的Eclipse的话,建议新建一个 Source Folder
叫Src_Config,然后就这个OSCache的属性文件放在其中.
修改这个OSCache的配置文件可以改变文件缓存的磁盘路径
置持久侦听等等.
5.如果你的jdk版本为1.3.x,
在lib中加入Apache Common Lib 的commons-collections.jar包。
jdk是1.4以上则不必.如果是需要集群缓存的话,
jgroups.jar放入包中。
6.把etc/META-INF/oscache.tld也放在/WEB-INF/classes下.
你的目录结构如下:
$WEB_APPLICATIONWEB-INFliboscache.jar
$WEB_APPLICATIONWEB-INFclassesoscache.properties
$WEB_APPLICATIONWEB-INFclassesoscache.tld
1.cache.properties 文件配置向导
cache.memory
值为true 或 false ,默认为在内存中作缓存,
如设置为false,那cache只能缓存到数据库或硬盘中,那cache还有什么意义
cache.persistence.class
持久化缓存类,如此类打开,则必须设置cache.path信息
cache.path
当使用磁盘缓存时,须指定目录如果不存在将被建立。同时注意
oscache应该要有权限写文件系统。
cache.path=c:\myapp\cache or *ix:
cache.path=/opt/myapp/cache
cache.capacity 缓存大小
cache.cluster.properties 为集群属性
cache.cluster.multicast.ip为广播IP地址
2.OSCache的基本用法
页面级缓存
应用OSCache的标签,我们必须先要引入进来.方式有两种
其一.在web.xml中加入:
<taglib>
<taglib-uri>oscache</taglib-uri>
<taglib-location>/WEB-INF/classes/oscache.tld</taglib-location>
</taglib>
然后我们在JSp中就可以<%@ taglib uri="oscache" prefix="os"%>这样来引用了.
其二,直接引用.直接在JSp中加入OSCache的标签库引用
<%@ taglib uri="/WEB- INF/classes/oscache.tld" prefix="os"%>.如果要进入官方的标签库的话也行<%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache"%>;这样就不用再把oscache.tld放在/WEB-INF/classes下了.
cache1.jsp 内容如下
<%@ taglib uri="/WEB-INF/classes/oscache.tld" prefix="cache" %>
<%@ page import="java.util.*" %>
<body>
没有缓存的日期: <%= new Date() %><p>
<!--自动刷新-->
<cache:cache time="30">
每30秒刷新缓存一次的日期: <%= new Date() %>
</cache:cache>
<br/>
<br/>
<!--手动刷新-->
<cache:cache key="testcache">
手动刷新缓存的日期: <%= new Date() %> <p>
</cache:cache>
<a href="cache2.jsp">手动刷新</a>
<!--不定义scope,scope默认为Applcation -->
<cache:cache time="30" scope="session">
每30秒刷新缓存一次的日期: <%= new Date() %>
</cache:cache>
</body>
Cache2.jsp 内容如下
<body>
缓存已刷新...<p>
<cache:flush key="testcache" scope="application"/>
<a href="cache1.jsp">返回</a>
</body>
注意:
CacheFilter只捕获Http头为200的页面请求,即只对无错误请求作缓存,而不对其他请求(如500,404,400)作缓存处理
对象级缓存
BaseCache 类
public class BaseCache extends GeneralCacheAdministrator {
// 过期时间(单位为秒);
private int refreshPeriod;
// 关键字前缀字符;
private String keyPrefix;
/**
* <pre>构造器
* @param keyPrefix
* @param refreshPeriod</pre>
*/
public BaseCache(String keyPrefix,int refreshPeriod){
super();
this.keyPrefix = keyPrefix;
this.refreshPeriod = refreshPeriod;
}
//添加被缓存的对象;
public void put(String key,Object value){
//调用父类的putInCache(String key,Object content)方法
this.putInCache(this.keyPrefix + "_" + key,value);
}
//添加被缓存的对象+过期时间
public void put(String key, Object value, int time) {
this.putInCache(this.keyPrefix + "_" + key, value, new ExpiresRefreshPolicy(time));
}
public void removeAll(){
//调用父类的flushAll()方法
this.flushAll();
}
//在给定时间清除缓存的对象; 1
public void removeAll(Date date){
//调用父类的flushAll(Date date)方法
this.flushAll(date);
}
//删除被缓存的对象;
public void remove(String key){
//调用父类的flushEntry(String key)方法
this.flushEntry(this.keyPrefix + "_" + key);
}
//获取被缓存的对象;
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 类
public class CacheManager {
private BaseCache userCache;
private static CacheManager instance;
private static Object lock = new Object();
private CacheManager() {
//这个根据配置文件来,初始BaseCache
baseCache = new BaseCache("CacheManager",120);
}
/**
* <pre>getInstance(单例化一个 CacheManager 单例模式:双重判定锁)
* @return CacheManager 对象</pre>
*/
public static CacheManager getInstance(){
if (instance == null){
synchronized( lock ){
if (instance == null){
instance = new CacheManager();
}
}
}
return instance;
}
/**
* <pre>putUser(将对象存入缓存中)
* @param 对象 </pre>
*/
public void putObj(String id,Object obj) {
baseCache.put(id,obj);
}
/**
* <pre>putObj(添加被缓存的对象+过期时间)
* @param id
* @param obj
* @param time</pre>
*/
public void putObj(String id,Object obj,int time) {
baseCache.put(id, obj, time);
}
/**
* <pre>removeUser(根据id 缓存中的对象移除)
* @param id</pre>
*/
public void removeObj(String id) {
baseCache.remove(id);
}
/**
* <pre>removeAllUser(删除缓存中所有的对象)
*/
public void removeAllObj(){
baseCache.removeAll();
}
/**
* <pre>removeAllUser(根据时间清除 缓存中所有的对象)
*/
public void removeAllObj(Date date){
baseCache.removeAll(date);
}
/**
* <pre>getUser(根据id 从缓存中提取对应的对象)
* @param id
* @return 对象 </pre>
*/
public Object getObj(String id,Object obj) {
try {
return baseCache.get(id);
} catch (Exception e) {
System.out.println("get>>id["+id+"]>>"+e.getMessage());
User user = new User(id);
this.putObj(id, obj);
return user;
}
} }
测试类
public static void main(String[] args) {
//将对象存入缓存中
CacheManager instance = CacheManager.getInstance();
//实例化一个用户对象
User user =new User();
user.setId("001");
user.setName("莉莉");
user.setSex("男");
user.setAge(15);
// 添加 缓存的对象
instance.putObj(user.getId(), user);
//添加 缓存的对象+过期时间
//instance.putObj(user.getId(), user, 5);
//从缓存中删除所有的用户对象
//instance.removeAllObj();
//从缓存中删除用户id 为001 的用户
//instance.removeObj(user.getId());
//在**时间从缓存中清除对象
//instance.removeAllObj(new Date());
//根据id 从缓存中取得用户数据
User userInfo = (User) instance.getObj(user.getId(), user);
System.out.println("User id is "+userInfo.getId());
System.out.println("User name is "+userInfo.getName());
System.out.println("User sex is "+userInfo.getSex());
System.out.println("User age is "+userInfo.getAge());
}
五、小结:
OSCache的使用主要有4种:
POJO 缓存
HTTP Response 缓存
在web.xml中定义缓存过滤器,定义特定资源的缓存。
<!-- 缓存过滤器 -->
<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>60</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>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
上面定义将缓存所有.jsp页面,缓存刷新时间为60秒,缓存作用域为Session
注意,只有返回状态为200(HttpServletResponse.SC_OK)的内容才会被缓存
JSP Tag Library 缓存
O/R Data Access 缓存