官網: 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