Spring+EhCache快取例項(詳細講解+原始碼下載)

執筆記憶的空白發表於2016-01-13

一、ehcahe的介紹

EhCache 是一個純Java的程式內快取框架,具有快速、精幹等特點,是Hibernate中預設的CacheProvider。Ehcache是一種廣泛使用的開源Java分散式快取。主要面向通用快取,Java EE和輕量級容器。它具有記憶體和磁碟儲存,快取載入器,快取擴充套件,快取異常處理程式,一個gzip快取servlet過濾器,支援REST和SOAP api等特點。

優點: 
1. 快速 
2. 簡單 
3. 多種快取策略 
4. 快取資料有兩級:記憶體和磁碟,因此無需擔心容量問題 
5. 快取資料會在虛擬機器重啟的過程中寫入磁碟 
6. 可以通過RMI、可插入API等方式進行分散式快取 
7. 具有快取和快取管理器的偵聽介面 
8. 支援多快取管理器例項,以及一個例項的多個快取區域 
9. 提供Hibernate的快取實現

缺點: 
1. 使用磁碟Cache的時候非常佔用磁碟空間:這是因為DiskCache的演算法簡單,該演算法簡單也導致Cache的效率非常高。它只是對元素直接追加儲存。因此搜尋元素的時候非常的快。如果使用DiskCache的,在很頻繁的應用中,很快磁碟會滿。 
2. 不能保證資料的安全:當突然kill掉java的時候,可能會產生衝突,EhCache的解決方法是如果檔案衝突了,則重建cache。這對於Cache資料需要儲存的時候可能不利。當然,Cache只是簡單的加速,而不能保證資料的安全。如果想保證資料的儲存安全,可以使用Bekeley DB Java Edition版本。這是個嵌入式資料庫。可以確儲存儲安全和空間的利用率。

EhCache的分散式快取有傳統的RMI,1.5版的JGroups,1.6版的JMS。分散式快取主要解決叢集環境中不同的伺服器間的資料的同步問題。

使用Spring的AOP進行整合,可以靈活的對方法的返回結果物件進行快取。

下面將介紹Spring+EhCache詳細例項。

二、詳細例項講解

本例項的環境 eclipse + maven + spring + ehcache + junit

2.1、相關依賴pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.luo</groupId>
  <artifactId>ehcache_project</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
        <!-- spring版本號 -->
        <spring.version>3.2.8.RELEASE</spring.version>
        <!-- junit版本號 -->
        <junit.version>4.10</junit.version>
  </properties>

  <dependencies>
        <!-- 新增Spring依賴 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--單元測試依賴 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!--spring單元測試依賴 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- ehcache 相關依賴  -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.8.2</version>
        </dependency>
    </dependencies>
</project>


2.2、新增ehcache配置檔案ehcache-setting.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!-- 指定一個檔案目錄,當EhCache把資料寫到硬碟上時,將把資料寫到這個檔案目錄下 -->
    <diskStore path="java.io.tmpdir"/>

    <!-- 設定快取的預設資料過期策略 -->
    <defaultCache
            maxElementsInMemory="10000" 
            eternal="false" 
            overflowToDisk="true"
            timeToIdleSeconds="10"
            timeToLiveSeconds="20"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"/>

    <cache name="cacheTest"
        maxElementsInMemory="1000"
        eternal="false"
        overflowToDisk="true"
        timeToIdleSeconds="10"
        timeToLiveSeconds="20"/>

</ehcache>


這裡我們配置了cacheTest策略,10秒過期。

cache元素的屬性:

name:快取名稱

maxElementsInMemory:記憶體中最大快取物件數

maxElementsOnDisk:硬碟中最大快取物件數,若是0表示無窮大

eternal:true表示物件永不過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,預設為false

overflowToDisk:true表示當記憶體快取的物件數目達到了

maxElementsInMemory界限後,會把溢位的物件寫到硬碟快取中。注意:如果快取的物件要寫入到硬碟中的話,則該物件必須實現了Serializable介面才行。

diskSpoolBufferSizeMB:磁碟快取區大小,預設為30MB。每個Cache都應該有自己的一個快取區。

diskPersistent:是否快取虛擬機器重啟期資料,是否持久化磁碟快取,當這個屬性的值為true時,系統在初始化時會在磁碟中查詢檔名為cache名稱,字尾名為index的檔案,這個檔案中存放了已經持久化在磁碟中的cache的index,找到後會把cache載入到記憶體,要想把cache真正持久化到磁碟,寫程式時注意執行net.sf.ehcache.Cache.put(Element element)後要呼叫flush()方法。

diskExpiryThreadIntervalSeconds:磁碟失效執行緒執行時間間隔,預設為120秒

timeToIdleSeconds: 設定允許物件處於空閒狀態的最長時間,以秒為單位。當物件自從最近一次被訪問後,如果處於空閒狀態的時間超過了timeToIdleSeconds屬性值,這個物件就會過期,EHCache將把它從快取中清空。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示物件可以無限期地處於空閒狀態

timeToLiveSeconds:設定物件允許存在於快取中的最長時間,以秒為單位。當物件自從被存放到快取中後,如果處於快取中的時間超過了 timeToLiveSeconds屬性值,這個物件就會過期,EHCache將把它從快取中清除。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示物件可以無限期地存在於快取中。timeToLiveSeconds必須大於timeToIdleSeconds屬性,才有意義

memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體。可選策略有:LRU(最近最少使用,預設策略)、FIFO(先進先出)、LFU(最少訪問次數)。

2.3、spring配置檔案application.xml

<?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:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="  
           http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
           http://www.springframework.org/schema/aop  
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/context  
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/cache 
           http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">

    <!-- 自動掃描註解的bean -->
    <context:component-scan base-package="com.luo.service" />

    <cache:annotation-driven cache-manager="cacheManager" />  

    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">  
        <property name="cacheManager" ref="ehcache"></property>  
    </bean>  

    <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">  
        <property name="configLocation" value="classpath:ehcache-setting.xml"></property>  
    </bean>  

</beans>


2.4、EhCacheTestService介面

package com.luo.service;

public interface EhCacheTestService {
    public String getTimestamp(String param);
}

2.5、EhCacheTestService介面實現

package com.luo.service.impl;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.luo.service.EhCacheTestService;

@Service
public class EhCacheTestServiceImpl implements EhCacheTestService {

    @Cacheable(value="cacheTest",key="#param")
    public String getTimestamp(String param) {
        Long timestamp = System.currentTimeMillis();
        return timestamp.toString();
    }

}

package com.luo.baseTest;

import org.junit.runner.RunWith;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  

//指定bean注入的配置檔案  
@ContextConfiguration(locations = { "classpath:application.xml" })  
//使用標準的JUnit @RunWith註釋來告訴JUnit使用Spring TestRunner  
@RunWith(SpringJUnit4ClassRunner.class)  
public class SpringTestCase extends AbstractJUnit4SpringContextTests {

}
package com.luo.service;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.luo.baseTest.SpringTestCase;

public class EhCacheTestServiceTest extends SpringTestCase {

    @Autowired  
    private EhCacheTestService ehCacheTestService;

    @Test  
    public void getTimestampTest() throws InterruptedException{  
        System.out.println("第一次呼叫:" + ehCacheTestService.getTimestamp("param"));
        Thread.sleep(2000);
        System.out.println("2秒之後呼叫:" + ehCacheTestService.getTimestamp("param"));
        Thread.sleep(11000);
        System.out.println("再過11秒之後呼叫:" + ehCacheTestService.getTimestamp("param"));
    } 
}



這裡註解中value=”cacheTest”與ehcache-setting.xml中的cache名稱屬性值一致。

2.6、單元測試類


2.7、執行結果

這裡寫圖片描述

三、工程原始碼下載

工程原始碼下載地址


原部落格地址:點選開啟連結

相關文章