ehcache的使用

来源:互联网 发布:知世与艾利欧结婚甜文 编辑:程序博客网 时间:2024/06/06 19:09

我们知道在CRUD中,一般来说一个项目中执行最多的应该就是查找select了,那么过多的数据库查找必然为降低系统的性能,这时候我们就必须想到要使用缓存了,缓存有很多种,我们近期要看的除了现在做的项目中用到的ehcache之外,还会关注马上要在公司全面使用的redis。作为技术架构组的一员,也是需要自己多研究这些东西,马上消息服务器也将由自己来负责,感觉要学的东西还是很多的。
好了,话不多说,我们先来看看ehcache在项目中结合Spring的使用吧。

首先我们给出相应的Maven依赖jar包。

      <dependency>       <groupId>net.sf.ehcache</groupId>       <artifactId>ehcache</artifactId>       <version>2.7.5</version>   </dependency>   <dependency>       <groupId>com.googlecode.ehcache-spring-annotations</groupId>       <artifactId>ehcache-spring-annotations</artifactId>       <version>1.2.0</version>   </dependency>

一个是ehcache自己的核心包,一个是google大佬提供的和Spring结合使用的注解相关包(Spring4及以上版本也有相应的ehcache注解了,应该可以不需要引入相关的注解包,这个我们下次深入的时候再看是否可以抛弃大佬的包)

二.ehcache配置文件

ehcache是个非常好用的缓存工具。(先知道怎么用的,然后看背后的原理等,不能只知道怎么用,但是也不能一上来卡卡整原理,那样太虚,只知道怎么用,那就会显得太肤浅,不扎实)
我们如果只是单纯的使用的话,只需要配置相应的配置文件。
我们看看配置文件的配置

<?xml version="1.0" encoding="UTF-8"?>    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">      <!-- http://blog.csdn.net/zheng963/article/details/50036619        可以自定义path           <diskStore path="java.io.tmpdir"/>        -->    <diskStore path="D:\ehcache"/>        <!--         name: cache的名字,用来识别不同的cache,必须惟一。   maxElementsInMemory: 内存管理的缓存元素数量最大限值。   maxElementsOnDisk: 硬盘管理的缓存元素数量最大限值。默认值为0,就是没有限制。   eternal: 设定元素是否持久话。若设为true,则缓存元素不会过期。   overflowToDisk: 设定是否在内存填满的时候把数据转到磁盘上。timeToIdleSeconds: 设定元素在过期前空闲状态的时间,只对非持久性缓存对象有效。默认值为0,值为0意味着元素可以闲置至无限长时间。   timeToLiveSeconds: 设定元素从创建到过期的时间。其他与timeToIdleSeconds类似。   diskPersistent: 设定在虚拟机重启时是否进行磁盘存储,默认为false.(我的直觉,对于安全小型应用,宜设为true)。   diskExpiryThreadIntervalSeconds: 访问磁盘线程活动时间。   diskSpoolBufferSizeMB: 存入磁盘时的缓冲区大小,默认30MB,每个缓存都有自己的缓冲区。   memoryStoreEvictionPolicy: 元素逐出缓存规则。共有三种,Recently Used (LRU)最近最少使用,为默认。 First In First Out (FIFO),先进先出。Less Frequently Used(specified as LFU)最少使用  -->     <defaultCache                  maxElementsInMemory="3000"                  eternal="false"                  timeToIdleSeconds="3600"                  timeToLiveSeconds="3600"                  overflowToDisk="true"                  diskPersistent="false"                  diskExpiryThreadIntervalSeconds="100"                  memoryStoreEvictionPolicy="LRU"                  />          <cache name="userCache"                 maxElementsInMemory="3000"                 eternal="false"                 overflowToDisk="true"                 timeToIdleSeconds="3600"                 timeToLiveSeconds="3600"                 memoryStoreEvictionPolicy="LFU"                  />      </ehcache>  

1)
这个是缓存存放的磁盘文件路径。默认path的值为java.io.tmpdir。
那java.io.tmpdir是什么呢。
我们看看在Windows下是什么,我们在程序中看看:

    System.out.println(System.getProperty("java.io.tmpdir"));   

打印结果为:C:\Users\cong\AppData\Local\Temp\
在不同的OS中,java.io.tmpdir指向的路径也不同:
- On Windows: java.io.tmpdir:[C:\DOCUME~1\joshua\LOCALS~1\Temp]

  • On Solaris: java.io.tmpdir:[/var/tmp/]

  • On Linux: java.io.tmpdir: [/tmp]

  • On Mac OS X: java.io.tmpdir: [/tmp]

2)
这个属性必须有,默认的cache。
有些没有被配置的缓存对象将使用默认缓存
maxElementsInMemory 内存中最大缓存对象数.当超过最大对象数的时候,ehcache会按指定的策略去清理内存
eternal 缓存对象是否永久有效,一但设置了,timeout将不起作用.
timeToIdleSeconds 设置Element在失效前的允许闲置时间.仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大.
timeToLiveSeconds timeToLiveSeconds:设置Element在失效前允许存活时间.最大时间介于创建时间和失效时间之间.仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大.
overflowToDisk 配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中.
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
maxElementsOnDisk 磁盘中最大缓存对象数,若是0表示无穷大.
diskPersistent 是否在重启服务的时候清楚磁盘上的缓存数据.true不清除.
diskExpiryThreadIntervalSeconds 磁盘失效线程运行时间间隔.
memoryStoreEvictionPolicy memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存.默认策略是LRU(最近最少使用).你可以设置为FIFO(先进先出)或是LFU(较少使用).
3)将ehcache和Spring关联起来。

<?xml version="1.0" encoding="UTF-8"?>  <!-- /** * * 缓存配置 *  * */ -->  <beans xmlns="http://www.springframework.org/schema/beans"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"      xsi:schemaLocation="          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd          http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring        http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd">      <!-- <ehcache:annotation-driven /> -->      <ehcache:annotation-driven cache-manager="ehcacheManager" />      <ehcache:config cache-manager="ehcacheManager">          <ehcache:evict-expired-elements interval="60" />      </ehcache:config>      <bean id="ehcacheManager"          class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">          <property name="configLocation" value="classpath:ehcache.xml" />      </bean>  </beans>  

Spring缓存配置,然后需要将其加入Spring主配置文件。

    <!-- 导入ehcache配置 -->      <import resource="classpath:applicationContext-ehcache.xml"/>  

三.使用Ehcache

package com.wangcc.ssm.dao;import java.util.List;import com.googlecode.ehcache.annotations.Cacheable;import com.wangcc.ssm.entity.Player;public interface PlayerDao {    // public void updatePlayerById();    @Cacheable(cacheName = "userCache")    public List<Player> getPlayerList();    public void insertPlayer(Player player);    public Player selectById(Integer id);}

使用注解@Cacheable cacheName必须与ehcache配置文件的cacheName相同。
配置好@Cacheable注解后,我们进行测试,发现缓存生效

    @Test    public void getListByDao() {        System.out.println("First Time");        long l1 = new Date().getTime();        List<Player> players = playerDao.getPlayerList();        long l2 = new Date().getTime();        System.out.println("++++++++++++total time use: " + (l2 - l1));        System.out.println("Second Time");        long l3 = new Date().getTime();        List<Player> players1 = playerDao.getPlayerList();        long l4 = new Date().getTime();        System.out.println("++++++++++++total time use: " + (l4 - l3));        logger.info(JSON.toJSONString(players1));    }

我们在方法上使用 @Cacheable后,发现第二次执行playerDao.getPlayerList();时,并不会执行该方法,而是直接就返回值了,这是怎么做到的呢?我们留到周末好好研究。