Oscache的使用详解

一、Oscache与Ehcache的区别

    1.对于两种缓存的组件个人理解觉得,两种缓存组件的功能是有差别的,Oscache可以缓存整个项目指定页面,也可以缓存指定网页某一部分,也可以缓存任何java对象,并指定过期时间;Oscache支持三种缓存存储,分别是内存,磁盘,另外一种比较灵活的方式,先缓存于内存中,如果满了则转至硬盘储。
    2.Ehcache主要是针对数据库访问的缓存,主要是针对后台数据库查询结果进行缓存,平时使用中,对一些不经常变动的系统参数,字典数据等,可以将数据查询出来以后缓存到Ehcache中,再次使用时,可以直接从缓存中取值,不用重复查询数据库。
    3.Oscache目前基已经很少使用,最后的版本是2.4.1, 最后一次更新日期2007/07/07,Ehcache比较活跃最新版本是3.5.2,使用人数比较多。
二、Oscache的使用
    Oscache的使用首先要下载Oscache组件
    下载路径 :http://www.opensymphony.com/oscache/
     所需jar包:
     oscache.jar
     commons-logging.jar
     配置步骤:
     第一步:把上述两个jar文件放置在WEB-INF/lib目录下.
     第二步:把oscache安装目录下的/etc/oscache.properties 系统配置文件目录src/下面
     第三步:把oscache.tld文件放到WEB-INF/下面,也可以加上自己的文件夹,比如我的项目中放置到WEB-INF/tld/

     1)、配置文件详解

1、cache.memory

是否使用内存缓存;值为:true或false。默认为true;如设置为false,那cache只能缓存到数据库或硬盘中。

2、cache.capacity

缓存的最大数量。默认是不限制,cache不会移走任何缓存内容。负数被视不限制。

3、cache.algorithm

运算规则。为了使用规则,cache的size必须是指定的。

如果cache的size不指定的话, 将不会限制缓存对象的大小。如果指定了cache的size,但不指定algorithm,那它会默认使用:com.opensymphony.oscache.base.algorithm.LRUCache

 有下面三种规则:

com.opensymphony.oscache.base.algorithm.LRUCache: last in first out(最后插入的最先调用)。默认选项。

com.opensymphony.oscache.base.algorithm.FIFOCache: first int first out(最先插入的最先调用)。

com.opensymphony.oscache.base.algorithm.UnlimitedCache: cache中的内容将永远不会被丢弃。如果cache.capacity不指定值的话,它将被设为默认选项。

4、cache.blocking

是否同步。true或者false。一般设为true,避免读取脏数据。

5、cache.unlimited.disk

指定硬盘缓存是否要作限制。默认值为false。false的状况下,disk cache capacity和cache.capacity的值相同。

6、cache.persistence.class

指定类是被持久化缓存的类。class必须实现PersistenceListener接口。

作为硬盘持久,可以实现com.opensymphony.oscache.plugins.diskpersistence.HashDiskPersistenceListener接口。

它把class的toString()输出的hash值作为文件的名称。如果你要想文件名易读些(自己设定),DiskPersistenceListener的父类也能使用,但其可能有非法字符或者过长的名字。

注意:HashDiskPersistenceListener和DiskPersistenceListener需要设定硬盘路径:cache.path

7、cache.path

指定硬盘缓存的路径。目录如果不存在将被建立。同时注意oscache应该要有权限写文件系统。

例:

cache.path=c:\\myapp\\cache

cache.path=/opt/myapp/cache

8、cache.persistence.overflow.only (NEW! Since 2.1)

指定是否只有在内存不足的情况下才使用硬盘缓存。

默认值false。但推荐是true如果内存cache被允许的话。这个属性彻底的改变了cache的行为,使得persisted cache和memory是完全不同。

9、cache.event.listeners

class名列表(用逗号隔开)。每个class必须实现以下接口中的一个或者几个。

CacheEntryEventListener:接收cache add/update/flush and remove事件

CacheMapAccessEventListener :接收cache访问事件。这个可以让你跟踪cache怎么工作。

默认是不配置任何class的。当然你可以使用一下class:

com.opensymphony.oscache.plugins.clustersupport.BroadcastingCacheEventListener: 分布式的监听器。可以广播到局域网内的其他cache实例。

com.opensymphony.oscache.extra.CacheEntryEventListenerImpl:一个简单的监听器。在cache的生命周期中记录所有entry的事件。

com.opensymphony.oscache.extra.CacheMapAccessEventListenerImpl: 记录count of cache map events(cache hits,misses and state hits).

10、cache.key

在application和session的作用域时,用于标识cache对象的,用于ServletCacheAdministrator;此属性不是指定为"__oscache_cache"格式时为默认值, 如果代码中需要用到默认值时可以通使用com.opensymphony.oscache.base.Const.DEFAULT_CACHE_KEY来取得;

11、cache.use.host.domain.in.key

当配置多个服务器时,想通过服备器名称自动生成cache key时,可将此属性设为true. 默认值为false;

12、Additional Properties

在以上基础选项之上可以加入一些额外的属性到此文件中.

例: JavaGroupsBroadcastingListener便是额外的.

13、cache.cluster.multicast.ip

用于缓存集群. 默认为231.12.21.132

14、cache.cluster.properties

指集群中的额外配置项

以上是某个大神对官方文档进行翻译后的描述。使用者可以根据项目的需求调整配置

  2)、全局配置,即对整个项目指定的页面进行缓存

1.需要先引入OSCache提供的标签,在web.xml文件中,添加一下配置

 <jsp-config>
    <taglib>
      <taglib-uri>oscache</taglib-uri>
      <taglib-location>/WEB-INF/tld/oscache.tld</taglib-location>
    </taglib>

  </jsp-config>

2.在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>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>
    <url-pattern>*.jsp</url-pattern>

  </filter-mapping>

这里面中的com.opensymphony.oscache.web.filter.CacheFilter是缓存的过滤器,当然也可以自己编写过滤器。参数中time指的是缓存时间,scope指的是缓存的作用域。下面的映射中,*.jsp缓存所有jsp页面,上面的定义中缓存所有.jsp页面,缓存刷新时间为600秒,缓存作用域为Session.

如果需要使用其他参数时,可以通过 <init-param>标签进行加载,标签内容应该与普通过滤器配置一致。

Oscache标签的说明,参考某位大神的文章

主要的标签以及标签属性
Cache标签——缓存代码段主要使用到的标签:
属性说明:
key
:标识缓存内容的关键词。在指定的作用范围内必须是唯一的。默认的key是被访问页面的URI和后面的请求字符串。可以在同一个页面中使用很多cache:标签而不指定他的key属性,这种情况下系统使用该页面的URI和后面的请求字符串,另外再自动给这些key增加一个索引值来区分这些缓存内 容。但是不推 荐采用这样的方式。
scope:
缓存发生作用的范围,可以是application或者session。默认为application。
time:
缓存内容的时间段,单位是秒,默认是3600秒,也就是一个小时,如果设定一个负值,那么这部分被缓存的内容将永远不过期。
duration:
指定缓存内容失效的时间,是相对time的另一个选择,可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等。
注意:time与duration的区别是time的单位是秒所以设置的时候是只要输入一个阿拉伯数字,而duration的话可以使用简单日期格式或者符合USO-8601的日期格式。如:duration='PT5M' duration='5s'等
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":表示每个星期一到星期五内容失效。
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,则这个值不起作用。
usecached标签:<usecached />必须嵌套在<cache>标签中。
属性说明:
   use:告诉所在的<cache>标签是否使用已经缓存的内容(缺省为true,使用缓存的内容)。可以使用这个标签来控制缓存。
       比如使用<frush>标签刷新某个key的缓存,但可以在必要的地方即使这样的强制刷新也仍然使用缓存内容而不刷新。
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属性来代替)
addgroup标签:<addgroup />必须嵌套在<cache>标签中。
属性说明: 
  group:定义cache标签的group名称
示例代码如下:
<oscache:cache key="test1">
    <oscache:addgroupgroup="group1" />
        ... some jsp content ...
    <oscache:addgroupgroup="group2" />
    ... some more jsp content ...
</oscache:cache>

   3)、页面局部缓存处理

        1、在web.xml引入Oscache标签,即需要在web.xml中配置

             <jsp-config>
                <taglib>
                  <taglib-uri>oscache</taglib-uri>
                  <taglib-location>/WEB-INF/tld/oscache.tld</taglib-location>
                </taglib>

             </jsp-config>

       2、在需要缓存的页面中引入Oscache的标签<%@taglib uri="oscache" prefix="cache" %>

      3.在需要缓存的地方可以使用<cache:cache> 标签进行缓存处理

        如:建立页面 index.jsp 内容如下

<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://www.opensymphony.com/oscache" prefix="oscache"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
现在时间:<%=new Date() %><br>
<oscache:cache>
缓存时间:<%=new Date() %>
</oscache:cache>
</body>
</html>

   将需要缓存的内容可以通过<oscache:cache>标签进行缓存

<oscache:cache>
缓存时间:<%=new Date() %>
</oscache:cache>

  如果此时访问该页面http://localhost:8080/mycache/index.jsp,第一次访问时,两个时间一致,如果刷新页面以后发现,缓存时间不变,与第一次访问时相同,如果改变访问路径即http://localhost:8080/mycache/index.jsp?time=随机数,那么两个时间有相同了,这说明,页面重新发起了请求,缓存中的key应该是URL,如果URL发生变化,缓存中找不到,那么就会重新发起请求,如果缓存中存在,就直接从缓存中取,缓存默认存放在application范围内

 <cache:cache key="name"> 可以为缓存独立起一个名字,这样的话,缓存的key就直接以这个name进行存储,不在以URL作为key。例如

<oscache:cache key='name'>
缓存时间:<%=new Date() %>
</oscache:cache>

下面是一个大神写的刷新的例子

  1. index1.jsp页面

  2. <!--手动刷新,给标记符key赋值了-->

  3. <cache:cache key="testcache">

  4.   手动刷新缓存的日期: <%= new Date() %> <p>

  5. </cache:cache>

  6. <ahref="index2.jsp">手动刷新</a>

  7. </body>

  8. </html>

  9. index2.jsp 执行手动刷新页面如下:

  10. <%@taglib uri="oscache" prefix="cache" %>

  11. <html>

  12. <body>

  13. 缓存已刷新...<p>

  14. <!—根据key定位到index1.jsp页面的testcache,范围为application,使用的是flush标签用来清空缓存-->

  15. <cache:flush key="testcache" scope="application"/>

  16. <a href="index1.jsp">返回</a>

  17. </body>

  18. </html>

Oscache标签可以指定缓存时间,也可以指定缓存作用域

例如:

<oscache:cache key='name' time='60' scope='session'>
...
</oscache:cache>

4)、关于缓存Java对象,这个直接参考一个例子

  1. Public class ChatRecordCache {  

  2.     private static GeneralCacheAdministrator admin;  

  3.     private static String OSCACHE_DISK =  "oscache_disk.properties";  

  4.     static {  

  5.         Properties prop = new Properties();   

  6.         try {  

  7.             prop.load(new FileInputStream(OSCACHE_DISK));  

  8.         } catch (FileNotFoundException e) {  

  9. //          e.printStackTrace();  

  10.         } catch (IOException e) {  

  11. //          e.printStackTrace();  

  12.         }  

  13.         admin = new GeneralCacheAdministrator(prop);  

  14.     }  

  15. }  

对应的配置文件为oscache_disk.properties: 

  1. cache.persistence.class=com.opensymphony.oscache.plugins.diskpersistence.DiskPersistenceListener  

  2. cache.path=/opt/myapp/cache  

  3. cache.algorithm=com.opensymphony.oscache.base.algorithm.FIFOCache  

  4. cache.capacity=1000  

  5. cache.unlimited.disk=true  

  1. public class ChatUserCache {  

  2.     private static GeneralCacheAdministrator admin = new GeneralCacheAdministrator();  

  3. }  

此处采用默认的配置文件oscache.properties. 
注意:如果多个cache实例产生的硬盘缓存路径和缓存名称完全相同,将会无法区分,此时要注意设置不同的key值区分。 
关于NeedsRefreshException,引用官方文档中的一段例子如下: 

  1. // ---------------------------------------------------------------  

  2. // Typical use with fail over  

  3. // 采取补救措施的典型方案  

  4. // ---------------------------------------------------------------  

  5.  String myKey = "myKey";  

  6.  String myValue;  

  7.  int myRefreshPeriod = 1000;  

  8.  try {  

  9.      // Get from the cache  

  10.      myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);  

  11.  } catch (NeedsRefreshException nre) {  

  12.     //This exception is thrown when retrieving an item from cache and it //is expired. Note that for fault tolerance purposes, it is possible //to retrieve the current cached object from the exception.  

  13.      try {  

  14.          // Get the value (probably by calling an EJB)  

  15.          myValue = "This is the content retrieved.";  

  16.          // Store in the cache  

  17.          admin.putInCache(myKey, myValue);//有解锁的作用  

  18.      } catch (Exception ex) {//获取myValue过程发生异常,无法执行到putInCache方法  

  19.          // We have the current content if we want fail-over.  

  20.          //采取补救措施,获取可能的值(适用于数据过期的情况)  

  21.     myValue = (String) nre.getCacheContent();  

  22.       

  23.          // It is essential that cancelUpdate is called if the  

  24.          // cached content is not rebuilt  

  25.          admin.cancelUpdate(myKey);//解锁  

  26.      }  

  27.  }  

这段代码是使用oscache的经典代码,细说如下。myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);从对象缓存map中取出myKey对应的对象,两种情况可能发生: 一:如果myKey对应的对象存在(先前putInCache)并且没有过期(isStale()方法)那么getFromCache方法会正常返回。二:如果对应的对象不存在或者过期,分为两种情况:1)请求的线程第一个探测到对象不存在或者过期,那么这个时候oscache会抛出一个NeedRefreshException, 提示需要对数据进行一下刷新,怎么刷新,putInCache或者cancelUpdate即可。2)如果请求的线程并非第一个探测到对象不存在,两种情况:A.之前探测到的线程没有进行刷新处理,直接阻塞。B. 之前探测到的线程进行了刷新处理,抛出NeedRefreshException。3)如果请求的线程并非第一个探测到对象过期,两种情况:A.之前探测到的线程没有进行刷新处理,直接阻塞。B. 之前探测到的线程进行了刷新处理,又分两种情况:I.如果oscache.properties中对blocking设置为false(默认cache.blocking=false), 抛出NeedRefreshException,此处采取补救措施nre.getCacheContent(),会取出现有(很可能过期)内容。 II. 如果cache.blocking=true那么该线程会在此阻塞,直到putInCache在另一个线程中被调用或者是cancelUpdate被调用。参考以下说明: 
cache.blocking 
When a request is made for a stale cache entry, it is possible that another thread is already in the process of rebuilding that entry. This setting specifies how OSCache handles the subsequent 'non-building' threads. The default behaviour (cache.blocking=false) is to serve the old content to subsequent threads until the cache entry has been updated. This provides the best performance (at the cost of serving slightly stale data). When blocking is enabled, threads will instead block until the new cache entry is ready to be served. Once the new entry is put in the cache the blocked threads will be restarted and given the new entry. 
Note that even if blocking is disabled, when there is no stale data available to be served threads will block until the data is added to the cache by the thread that is responsible for building the data. 

补充:oscache对一个cacheEntry是否是Stale(或者说expire)的判断原则: 
1.Cache.flushEntry() 
2.Cache.flushAll() 
3.CacheEntry.setGroups(groups); Cache.flushGroup(group) 
4.createTime + refreshPeriod< now 
5.cronExpiry< now 
6.CacheEntry自带的EntryRefreshPolish的needRefresh方法返回true 
上面的6条中的任何一条如果为true, 那么CacheEntry就是stale的,need refresh! 
官方文档中的另一段例子如下: 

  1. // ---------------------------------------------------------------  

  2. // Typical use without fail over  

  3. //不采取补救措施的典型方案  

  4. // ---------------------------------------------------------------  

  5.  String myKey = "myKey";  

  6.  String myValue;  

  7.  int myRefreshPeriod = 1000;  

  8.  try {  

  9.      // Get from the cache  

  10.      myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);  

  11.  } catch (NeedsRefreshException nre) {  

  12.      try {  

  13.          // Get the value (probably by calling an EJB)  

  14.          myValue = "This is the content retrieved.";  

  15.          // Store in the cache  

  16.          admin.putInCache(myKey, myValue);  

  17.          updated = true;  

  18.      } finally {  

  19.          if (!updated) {  

  20.              // It is essential that cancelUpdate is called if the  

  21.              // cached content could not be rebuilt  

  22.              admin.cancelUpdate(myKey);  

  23.          }  

  24.      }  

  25.  }  

  26.  // ---------------------------------------------------------------  




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值