代码改变世界

OScached页面缓存的概念和安装

2017-11-15 22:32  晨曦曙光  阅读(635)  评论(0编辑  收藏  举报

一、基本概述

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_APPLICATION\WEB-INF\lib\oscache.jar
$WEB_APPLICATION\WEB-INF\classes\oscache.properties
$WEB_APPLICATION\WEB-INF\classes\oscache.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 缓存