一、ehcahe的介紹
EhCache 是一個純Java的進程內(nèi)緩存框架,具有快速、精干等特點,是Hibernate中默認的CacheProvider。Ehcache是一種廣泛使用的開 源Java分布式緩存。主要面向通用緩存,Java EE和輕量級容器。它具有內(nèi)存和磁盤存儲,緩存加載器,緩存擴展,緩存異常處理程序,一個gzip緩存servlet過濾器,支持REST和SOAP api等特點。
優(yōu)點:?
1. 快速?
2. 簡單?
3. 多種緩存策略?
4. 緩存數(shù)據(jù)有兩級:內(nèi)存和磁盤,因此無需擔(dān)心容量問題?
5. 緩存數(shù)據(jù)會在虛擬機重啟的過程中寫入磁盤?
6. 可以通過RMI、可插入API等方式進行分布式緩存?
7. 具有緩存和緩存管理器的偵聽接口?
8. 支持多緩存管理器實例,以及一個實例的多個緩存區(qū)域?
9. 提供Hibernate的緩存實現(xiàn)
缺點:?
1. 使用磁盤Cache的時候非常占用磁盤空間:這是因為DiskCache的算法簡單,該算法簡單也導(dǎo)致Cache的效率非常高。它只是對元素直接追加存儲。因此搜索元素的時候非常的快。如果使用DiskCache的,在很頻繁的應(yīng)用中,很快磁盤會滿。?
2. 不能保證數(shù)據(jù)的安全:當(dāng)突然kill掉java的時候,可能會產(chǎn)生沖突,EhCache的解決方法是如果文件沖突了,則重建cache。這對于Cache 數(shù)據(jù)需要保存的時候可能不利。當(dāng)然,Cache只是簡單的加速,而不能保證數(shù)據(jù)的安全。如果想保證數(shù)據(jù)的存儲安全,可以使用Bekeley DB Java Edition版本。這是個嵌入式數(shù)據(jù)庫??梢源_保存儲安全和空間的利用率。
EhCache的分布式緩存有傳統(tǒng)的RMI,1.5版的JGroups,1.6版的JMS。分布式緩存主要解決集群環(huán)境中不同的服務(wù)器間的數(shù)據(jù)的同步問題。
下面將介紹SpringMVC+EhCache詳細實例。
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.maven.web</groupId>
<artifactId>springMVC</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springMVC Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.3.RELEASE</version>
</dependency>
<!-- ehcache 相關(guān)依賴 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<build>
<finalName>springMVC</finalName>
</build>
</project>
2、index.jsp 文件如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
? ? pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!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>hello page</title>
<script type="text/javascript" src="<%=basePath%>js/jquery.js" ></script>
</head>
<script>
function cunchu(){
? $.post("welcome/saveEcache", function(data) {
? alert("success");
? });
}
function huoqu(){
? ? $.post("welcome/getEcache", function(data) {
? alert(data);
? ? });
}
</script>
<body>
<div style="text-align: left;">
<input type="button" value="存儲數(shù)據(jù)" onclick="cunchu()">
<input type="button" value="獲取數(shù)據(jù)" onclick="huoqu()">
</div>
</body>
</html>
3、mvc-dispatcher-servlet.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
? ? ? ? http://www.springframework.org/schema/beans? ?
? ? ? ? http://www.springframework.org/schema/beans/spring-beans-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/mvc
? ? http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
? ? ? ? http://www.springframework.org/schema/cache
? ? ? ? http://www.springframework.org/schema/cache/spring-cache-3.1.xsd">
<!-- 說明:增加本段配置是為了解決增加<mvc:annotation-driven/>配置后的編碼問題,要放在<mvc:annotation-driven/>之前
等效 produces = "application/json; charset=utf-8" -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
? ? <cache:annotation-driven cache-manager="cacheManager" />?
<context:component-scan base-package="com.bufan.demo.controller" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
? ? <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="/WEB-INF/ehcache-setting.xml"></property>?
? ? </bean>?
</beans>
4、ehcache-setting.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!-- 指定一個文件目錄,當(dāng)EhCache把數(shù)據(jù)寫到硬盤上時,將把數(shù)據(jù)寫到這個文件目錄下 -->
<diskStore path="java.io.tmpdir"/>
<!-- 設(shè)定緩存的默認數(shù)據(jù)過期策略 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="10"
timeToLiveSeconds="20"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"/>
<cache name="cacheTest1"
? ? ? ? maxElementsInMemory="1000"
? ? ? ? eternal="false"
? ? ? ? overflowToDisk="true"
? ? ? ? timeToIdleSeconds="100"
? ? ? ? timeToLiveSeconds="200"/>
? ? ?<cache name="cacheTest3"
? ? ? ? maxElementsInMemory="1000"
? ? ? ? eternal="false"
? ? ? ? overflowToDisk="true"
? ? ? ? timeToIdleSeconds="1000"
? ? ? ? timeToLiveSeconds="2000"/>
</ehcache>
這里我們配置了cacheTest策略,1000秒過期。
cache元素的屬性:
name:緩存名稱
maxElementsInMemory:內(nèi)存中最大緩存對象數(shù)
maxElementsOnDisk:硬盤中最大緩存對象數(shù),若是0表示無窮大
eternal:true表示對象永不過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認為false
overflowToDisk:true表示當(dāng)內(nèi)存緩存的對象數(shù)目達到了
maxElementsInMemory界限后,會把溢出的對象寫到硬盤緩存中。注意:如果緩存的對象要寫入到硬盤中的話,則該對象必須實現(xiàn)了Serializable接口才行。
diskSpoolBufferSizeMB:磁盤緩存區(qū)大小,默認為30MB。每個Cache都應(yīng)該有自己的一個緩存區(qū)。
diskPersistent:是否緩存虛擬機重啟期數(shù)據(jù),是否持久化磁盤緩存,當(dāng)這個屬性的值為true時,系統(tǒng)在初始化時會在磁盤中查找文件名 為cache名稱,后綴名為index的文件,這個文件中存放了已經(jīng)持久化在磁盤中的cache的index,找到后會把cache加載到內(nèi)存,要想把 cache真正持久化到磁盤,寫程序時注意執(zhí)行net.sf.ehcache.Cache.put(Element element)后要調(diào)用flush()方法。
diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認為120秒
timeToIdleSeconds: 設(shè)定允許對象處于空閑狀態(tài)的最長時間,以秒為單位。當(dāng)對象自從最近一次被訪問后,如果處于空閑狀態(tài)的時間超過了timeToIdleSeconds屬性 值,這個對象就會過期,EHCache將把它從緩存中清空。只有當(dāng)eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限 期地處于空閑狀態(tài)
timeToLiveSeconds:設(shè)定對象允許存在于緩存中的最長時間,以秒為單位。當(dāng)對象自從被存放到緩存中后,如果處于緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清除。只有當(dāng)eternal屬性為false,該屬性才有 效。如果該屬性值為0,則表示對象可以無限期地存在于緩存中。timeToLiveSeconds必須大于timeToIdleSeconds屬性,才有 意義
memoryStoreEvictionPolicy:當(dāng)達到maxElementsInMemory限制時,Ehcache將會根據(jù)指定的策略去清理內(nèi)存??蛇x策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數(shù))。
5、HelloController 文件:
package com.bufan.demo.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
@Controller
@RequestMapping("/welcome")
public class HelloController {
@RequestMapping(value="rol",method=RequestMethod.GET)
public String printWelcome(ModelMap model){
model.addAttribute("message", "springMVC 例子");
SimpleDateFormat format=new SimpleDateFormat();
model.addAttribute("date",format.format(new Date()));
? ? return "hello";
}
@RequestMapping(value="saveEcache")
public void cunchu(ModelMap model,HttpServletResponse response) {
try {
PrintWriter out = response.getWriter();
Map<String, String> map=new HashMap<String, String>();
map.put("1", "test1");
map.put("2", "test2");
? ? ? ? Cache cache = LazySingleton.getInstance().getCache("cacheTest1");
? ? ? ? cache.put(new Element("param4", map));
? ? ? ? Element element2 = cache.get("param4");
? ? ? ? System.out.println("value====="+element2.getValue());//獲取緩存值
? ? ? ? out.print(model);
? ? out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@RequestMapping(value="getEcache")
public void huoqu(ModelMap model,HttpServletResponse response) {
? ? ? ? try {
PrintWriter out = response.getWriter();
Element element2 = LazySingleton.getInstance().getCache("cacheTest1").get("param4");
? ? System.out.println("value====="+element2.getValue());//獲取緩存值
? ? model.addAttribute("data",element2.getValue());
? ? out.print(model);
? ? out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
6、LazySingleton
package com.bufan.demo.controller;
import net.sf.ehcache.CacheManager;
public class LazySingleton {
//私有靜態(tài)變量,加載時不初始化
? ? private static CacheManager lazySingleton = null;
? ? //私有的構(gòu)造方法,避免外部創(chuàng)建實例
? ? private LazySingleton(){
? ? }
? ? synchronized public static CacheManager getInstance(){
? ? ? if(lazySingleton == null){
? ? ? lazySingleton =? CacheManager.create();;
? ? ? }
? ? ? return lazySingleton;? ? ?
? ? }
}
二、 運行結(jié)果
