官网: http://www.opensymphony.com/oscache [缓存产品有:EHCahce、OSCache、JbossCache(分布式缓存)]
例子:http://www.java.net/downloads/oscache/OSCache/2.4.1/oscache-example.war
OSCache是什么
OSCache是OpenSymphony这个开源项目众多Projects中的一个。他是一个高效的J2EE缓存框架,能够很好的解决动态网站速度的问题。下面来看下OSCache解决了动态网站的哪些令人郁闷的问题。
1.缓存动态内容:其实我们的动态网页上一般只有一部分是动态的(表头,表尾一般是不变的),如果我们缓存整个网页显然不成,因为有部分是随着请求有可能变的。OSCache提供的方式是允许我们只缓存一部分网页。
2.缓存2进制内容:产生的图片和PDF文件在服务器加载的时候非常的耗时。OSCache解决这个问题是通过一个Servlet2.3的缓存过滤功能,然后能够缓存任意的URI(比如一个完整的页面或者是一个产生的图片/PDF文件)
3.容错:有这种情况或许我们会遇到,就是当一个动态的网页出现错误。即便我们的页面有95%都加载完毕,但就是由于这个错误,整个页面就会返回错误的提示或页面。OSCache允许我们提供出现错误时的缓存内容,如果出现就适时的提示出来了。
除了上面的这些Servlet的特征外,OSCache完全可以充当任何一个java程序的缓存方案。OSCache 的一般特征如下:
1.缓存任意对象:可以不受限制的缓存JSP的一部分或是Http请求,任何的Java对象都可以被缓存。
2.全面的API:通过API可以完完全全的控制OSCache的任何特性。
3.持久缓存:我们可以把认为重要的数据缓存到硬盘上。
4.支持集群:集群缓存数据能被单个的进行参数配置,不需要修改代码(如果需要集群缓存,把jgroups.jar放入classpath)
5.缓存记录的过期:你可以有最大限度的控制缓存对象的过期,包括可插入式的刷新策略(如果默认性能不需要时)。
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缓存配置
从src\webapp\WEB-INF\classes或etc目录取得oscache.properties文件,放在CLASSPATH下src根目录,oscache.properties包含了对OSCache运行特征值的设置信息
配置项 |
含义 |
可选值 |
缺省值 |
cache.memory |
是否进行内存缓存 |
true、false |
true |
cache.capacity |
内存缓存容纳的最大对象数 |
整数 |
不限制(指定负数也相当于不限制),也就是缓存的对象从不被清除 |
cache.algorithm |
缺省的运算规则。要指定运算规则,就必须指定有效的cache.capacity值(正整数)。规则是一些类,在包com.opensymphony.oscache.base.algorithm下 |
LRUCache(最近使用)、FIFOCache(先进先出)、UnlimitedCache(不限制) |
不限制cache.capacity时为UnlimitedCache,If you specify a size but not an algorithm, the cache algorithm used will be LRUCache |
cache.blocking |
当缓存中的某条数据更新时(比如与数据库不同步,存在不新鲜的数据),对客户请求返回更新前的数据。这样就提供了更好的性能。 |
true、false |
false |
cache.unlimited.disk |
硬盘缓存是否有限制。缺省为cache.capacity指定的值 |
true、false |
false |
cache.persistence.class |
做持久化操作的类名。这个类必须实现PersistenceListener接口,从而将缓存数据持久化到文件、数据库、LDAP。OSCache给出一个基于文件系统的实现,并且使用对象的toString()方法生成要持久化数据的文件名。HashDiskPersistenceListener和 DiskPersistenceListener要求必须同时设置cache.path属性。 |
com.opensymphony.oscache.plugins. diskpersistence.DiskPersistenceListener |
|
cache.path |
硬盘持久化时存放文件的目录。如果目录不存在OSCache会自动创建。 |
Windows系统: c:\\myapp\\cache 其它:/opt/myapp/cache |
|
cache.persistence.overflow.only* |
是否只有当指定的内存缓存已经满时才进行持久化。推荐使用true,flase是为向后兼容。 |
true、false |
false |
cache.event.listeners |
一系列用逗号分割的类,这些类必须实现CacheEntryEventListener或(和)CacheMapAccessEventListener接口,CacheEntryEventListener监听缓存的add/update/flush/remove事件,CacheMapAccessEventListener监听缓存的access事件,从而可以跟踪并统计缓存的执行效率。JavaDoc API for further details. |
|
|
cache.key |
指定在application或session范围里缓存的对象的key,这个key被ServletCacheAdministrator(由此自定义的tags)使用。 |
|
__oscache_cache |
cache.use.host.domain.in.key |
If your server is configured with multiple hosts, you may wish to add host name information to automatically generated cache keys. If so, set this property to true |
truefalse |
false |
cache.cluster.multicast.ip |
见集群的相关说明 |
|
|
cache.cluster.properties |
见集群的相关说明 |
|
|
缓存方式
1.缓存对象(内存缓存,磁盘缓存)
将一个对象以key-value的形式放入缓存中,主要通过GeneralCacheAdministrator类来实现。写了个单例,其实是不必要的
public class OSCacheHelper<T> extends GeneralCacheAdministrator { private static final long serialVersionUID = 1L; private static Logger logger = Logger.getLogger(OSCacheHelper.class); private static Object lock = new Object(); private static OSCacheHelper instance; private OSCacheHelper() { } public static OSCacheHelper getInstance() { if (instance == null) { synchronized (lock) { if (instance == null) { instance = new OSCacheHelper(); } } } return instance; } /** * put on Object in a cache */ public void putToCache(String key, T data) { try { this.putInCache(key, data); logger.info(key + " put in Cache success"); } catch (Exception e) { logger.info(key + " put in Cache faile"+e.getMessage()); } } /** * get on Object from the Cache */ public T getFromCache(String key, int time) { try { return (T) this.getFromCache(key, time); } catch (Exception e) { logger.info(key + " is not found in Cache"); } return null; } /** * remove an Object in a cache */ public void removeEntry(String key) { this.removeEntry(key); } /** * flushes a single cache entry */ public void flushEntry(String key) { this.flushEntry(key); } /** * flush the entire cache immediately */ public void flushAll() { this.flushAll(); } /* * cancel a pending cache update */ public void cancelUpdate(String key) { this.cancelUpdate(key); } /** * 删除指定日期所有被缓存的对象 */ public void flushAll(Date date) { this.flushAll(date); } }
SpringMVC下测试
@Controller public class OscaheController extends BaseCache { private static final long serialVersionUID = 1L; protected static Logger logger = Logger.getLogger(OscaheController.class); // 文件缓存读取 @RequestMapping(value = "putCache.shtml") public String putCache() { Map<String, List<User>> ms_map = new HashMap<String, List<User>>(); List<User> list = new ArrayList<User>(); for (int j = 0; j < 100; j++) { for (int i = 0; i < 500; i++) { User user = new User(); user.setId(i); user.setEmail(2538XXXXX + i + "@163.com"); user.setNickname("Irving"); user.setUsername("sd" + new Date().toLocaleString()); user.setAdddate(new Date()); list.add(user); } ms_map.put(String.valueOf(list.get(0).getId()), list); } //this.putToCache("CACHE_NEW_MS_PRICE_OBJ", ms_map); OSCacheHelper.getInstance().putToCache("CACHE_NEW_MS_PRICE_OBJ", ms_map); return "putCache"; } @RequestMapping(value = "loadCache.shtml") public void loadCache() { Map<String, List<User>> ms_map = new HashMap<String, List<User>>(); ms_map = (Map<String, List<User>>) this.getFromCache("CACHE_NEW_MS_PRICE_OBJ", 31536000); for (Object o : ms_map.keySet()) { List<User> user = ms_map.get(o); for (User u : user) { logger.info("ID:" + u.getId() + " Email:" + u.getEmail() + " UserName:" + u.getUsername()); } } } }
2.局部页面缓存(导入标签库)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page language="java" import="java.text.*" %> <%@ taglib uri="http://www.opensymphony.com/oscache" prefix="cache"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>页面局部缓存</title> </head> <body> <% SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); %> <div> <cache:cache key="cacheDate" scope="session" time="10"> <h2>使用缓存,在10秒内不进行更新</h2> <div><% String cacheTime = sf.format(new Date()); out.println(cacheTime); %> </div> </cache:cache> </div> <hr> <div> <h2>不使用缓存</h2> <div><% String nowTime = sf.format(new Date()); out.println(nowTime); %></div> </div> </body> </html>
3.整个页面缓存
<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>500</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> <!-对所有shtml页面内容进行缓存--> <url-pattern>*.shtml</url-pattern> </filter-mapping>
4.分布式缓存(没有研究)
小结
1、清除缓存:
<!-- refresh为true将会导致缓存的内容过期而被清除,简单地说,该属性为true用于清除缓存 --> <!-- <oscache:flush scope="application"/>清除application范围内的所有缓存; <oscache:flush scope="session" key="huhui"/> #清除session范围内的key为huhui的缓存 <oscache:flush scope="application" group="hu"/> #清除application范围内组名为hu内的所有缓存 --> <%@ page language="java" pageEncoding="UTF-8"%> <%@taglib uri="http://www.opensymphony.com/oscache" prefix="oscache" %> <oscache:flush scope="applocation"/> #缓存已清除
2、局部缓存:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://www.opensymphony.com/oscache" prefix="oscache" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body><!-- 这是局部缓存 --> <oscache:cache key="huhui" scope="session" time="15" refresh="${param.refresh }"> <!-- 是使用Map对象来存储缓存的,默认的key是uri路径,如:/oscache/index.jsp,也可以指定它的key --> <!-- 缓存默认存放在application范围,缓存时间默认为3600秒,即1小时 --> <div><%=new Date() %></div> </oscache:cache> 当前时间:<%=new Date() %> </body> </html>
3、全局缓存: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>7200</param-value> </init-param> <init-param> <param-name>scope</param-name> <param-value>application</param-value> </init-param> </filter> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>/hotel/list.shtml</url-pattern> </filter-mapping>
4、内存缓存/硬盘缓存推荐使用内存缓存,比硬盘缓存要快
oscache.properties #指定是否使用内存缓存,默认值为true,即使用内存缓存 cache.memory=true #指定缓存的容量,默认的容量是无限的 cache.capacity=10000 #如果要使用硬盘缓存,可以这样设置: cache.memory=false #指定缓存保存的路径 cache.path=/opt/springmvc/cache #用于设置持久化的类
cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener
Refer:
http://blog.chinaunix.net/uid-122937-id-142910.html
http://blog.csdn.net/zhifeng172/article/details/7608682
http://blog.csdn.net/orclight/article/category/1331444