EhCache介绍:http://chenjumin.iteye.com/blog/684926
ehcache-setting.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
<diskStore path="java.io.tmpdir"/>
<!-- 设定缓存的默认数据过期策略 -->
<!--timeToIdleSeconds 当缓存闲置n秒后销毁 -->
<!--timeToLiveSeconds 当缓存存活n秒后销毁 -->
<!--
缓存配置
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="10"
timeToLiveSeconds="20"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache name="cacheWeather"
maxElementsInMemory="100000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="300"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
applicationContext.xml
<!-- EhCache start -->
<!-- 启用缓存注解功能,这个是必须的,否则注解不会生效,另外,该注解一定要声明在spring主配置文件中才会生效 -->
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- 声明cacheManager -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache"></property>
</bean>
<!-- cacheManager工厂类,指定ehcache.xml的位置 -->
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache-setting.xml"></property>
</bean>
<!-- EnCache end -->
使用标签:
/**
* value:缓存位置名称,不能为空,如果使用EHCache,就是ehcache.xml中声明的cache的name
* key:缓存的key,默认为空,既表示使用方法的参数类型及参数值作为key,支持SpEL
* condition:触发条件,只有满足条件的情况才会加入缓存,默认为空,既表示全部都加入缓存,支持SpEL
*/
//将缓存保存进andCache,并使用参数中的userId加上一个字符串(这里使用方法名称)作为缓存的key
@Cacheable(value="cacheWeather",key="#lat.substring(0,5)+#lon.substring(0,6)")
public List<ResponseDataItemPojo> getCurrentWeather(String lat, String lon,
String language) throws JsonParseException, JsonMappingException,
@Cacheable(value="cacheTest",key="#param")
public String getTimestamp(String param) {
Long timestamp = System.currentTimeMillis();
return timestamp.toString();
}
//将缓存保存进andCache,并使用参数中的userId加上一个字符串(这里使用方法名称)作为缓存的key
@Cacheable(value="cacheTest",key="#userId + 'findById'")
public UserTest findById(Long userId) {
UserTest user = userTestDao.queryUserByid(userId);
System.out.println("数据库查询..........");
return user ;
}
//将缓存保存进andCache,并当参数userId的长度小于8时才保存进缓存,默认使用参数值及类型作为缓存的key
@Cacheable(value="andCache",condition="#userId.length()< 8")
public boolean isReserved(String userId) {
System.out.println("hello andCache "+userId);
userTestDao.queryUserByid(Long.getLong(userId));
return false;
}
// @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
@Cacheable(value="cacheTest",key="#id")
public UserTest queryById(Long id) {
System.out.println("数据库查询..........");
return userTestDao.queryUserByid(id);
}
//@Cacheable(value="users", key="#p0") 使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”
@Cacheable(value="cacheTest",key="#p0")
public UserTest queryById(Long id,String name) {
System.out.println("数据库查询..........");
return userTestDao.queryUserByid(id);
}
@Cacheable(value="cacheTest",key="#root.methodName")
public List<UserTest> queryList(){
return userTestDao.queryList();
}
//当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性
@Cacheable(value="cacheTest",key="methodName")
public UserTest queryById(){
return userTestDao.queryUserByid(12l);
}
/**
* key的名称一样然后类型一样就会干扰缓存结果
*/
//测试缓存干扰
//测试缓存key一样时的状况
@Cacheable(value="cacheTest",key="#id")
public List<UserTest> queryList(Long id){
return userTestDao.queryList();
}
EhCacheManager
不用标签时的工具类:
package com.gongren.ehCache;
import java.io.Serializable;
import java.net.URL;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import com.gongren.daoCache.QueryMsgTestDao;
import com.gongren.entity.MyCacheObject;
import com.gongren.entity.UserTest;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.Status;
public class EhCacheManager {
private static Logger logger = Logger.getLogger(EhCacheManager.class);
/**
* Ehanche的缓存管理
*/
private static CacheManager cacheManager = null;
private static String configPath="ehcache-setting.xml";//配置文件
private QueryMsgTestDao queryMsgTestDao;//查询
//缓存定义
public static String CACHE_MYCOMMONCACHE="cacheTest";//定义文件中配置的缓存
//缓存中的Element定义
public static String ELEMENT_MYCOMMONCACHE_DICTIONARY="dictionaryList";//缓存元素
//实例化cacheManager,单例模式
public static CacheManager getCacheManagerInstance(){
if(cacheManager==null){
synchronized(EhCacheManager.class){//线程安全
URL configUrl=null;
configUrl = EhCacheManager.class.getClassLoader().getResource(configPath);
cacheManager = CacheManager.create(configUrl);
}
}
return cacheManager;
}
public static CacheManager getCacheManager() {
return getCacheManagerInstance();//单例缓存管理
}
public static void setCacheManager(CacheManager cacheManager) {
EhCacheManager.cacheManager = cacheManager;
}
public QueryMsgTestDao getQueryMsgTestDao() {
return queryMsgTestDao;
}
public void setQueryMsgTestDao(QueryMsgTestDao queryMsgTestDao) {
this.queryMsgTestDao = queryMsgTestDao;
}
//添加新缓存
public static void addCacheByName(String cacheName){
if(cacheName==null||cacheName.trim().equals("")){
logger.error("cacheName is null");
}else{
if(getCacheManager().getCache(cacheName.trim())!=null){
getCacheManager().removeCache(cacheName.trim());
}
getCacheManager().addCache(cacheName.trim());
logger.info(cacheName+ "is add complete");
}
}
//得到cache对象
public static Cache getCacheByName(String cacheName){
Cache cache=null;
if(cacheName==null||cacheName.trim().equals("")){
logger.error("cacheName is null");
}else{
if(getCacheManager().getCache(cacheName.trim())!=null){
cache=getCacheManager().getCache(cacheName.trim());
}else{
logger.error("cacheName is not existent");
}
}
return cache;
}
//往缓存中添加元素
public static void putElementToCache(String cacheName,String elementKey,Object elementValue){
Cache cache=null;
if(cacheName==null||cacheName.trim().equals("")){
logger.error("Failed to add cache element,cacheName is null");
}else if(StringUtils.isEmpty(elementKey)||StringUtils.isEmpty(elementValue)){
logger.error("Failed to add cache element,elementKey or elementValue is null");
}else{
if(getCacheByName(cacheName.trim())!=null){//缓存存在
cache=getCacheByName(cacheName.trim());
}else{//缓存不存在
addCacheByName(cacheName.trim());
cache=getCacheByName(cacheName.trim());
}
//对cache对象添加Element
Element element=null;
if(cache.get(elementKey.trim())!=null){
cache.remove(elementKey.trim());
}
element=new Element(elementKey.trim(),elementValue);
cache.put(element);
logger.info("add element:"+elementKey+" success!");
}
}
//从缓存中获取指定key的值
public static Object getElementValueFromCache(String cacheName,String elementKey){
Object result=null;
Cache cache=null;
if(cacheName==null||cacheName.trim().equals("")){
logger.error("Failed to get cache element,cacheName is null");
}else if(elementKey==null){
logger.error("Failed to get cache element,elementKey is null");
}else{
if(getCacheByName(cacheName.trim())!=null){//缓存存在
cache=getCacheByName(cacheName.trim());
Element element=null;
if(cache.get(elementKey.trim())!=null){
element=cache.get(elementKey.trim());
if(element.getObjectValue()==null){
logger.error("The value of "+elementKey+" in the cache is empty");//缓存中的 elementKey的value为空
}else{
result=element.getObjectValue();
}
}else{
logger.error("There is no:"+elementKey+" in the cache"); //缓存中无elementKey
}
}else{//缓存不存在
logger.error("Failed to get cache element,The element:"+cacheName+" in the cache is empty");
}
}
return result;
}
/**
* 获取缓存的Keys
*
* @param cacheName
* @return
*/
@SuppressWarnings("unchecked")
public static List<String> getKeys(String cacheName) {
Ehcache cache = getCacheManager().getEhcache(cacheName);
return (List<String>) cache.getKeys();
}
/**
* 把所有cache中的内容删除,但是cache对象还是保留.
* Clears the contents of all caches in the CacheManager,
* but without removing any caches.
*/
public static void clearAllFromCacheManager(){
if(getCacheManager()!=null){
getCacheManager().clearAll();
logger.info("CacheManager was clearAll...");
}
}
/**
* 删除指定对象
*
* @param cacheName
* @param key
* @return
*/
public static boolean remove(String cacheName, String key) {
return getCacheManager().getCache(cacheName).remove(key);
}
/**
* 把所有cache对象都删除。慎用!
* Removes all caches using removeCache(String) for each cache.
*/
public static void removalAllFromCacheManager(){
if(getCacheManager()!=null){
getCacheManager().removalAll();
logger.info("CacheManager was removalAll...");
}
}
/**
* 获取缓存大小
*
* @param cacheName
* @return
*/
public static int getSize(String cacheName) {
return getCacheManager().getCache(cacheName).getSize();
}
//不用缓存时,要关闭,不然会占用cpu和内存资源。
public static void shutdownCacheManager(){
if(getCacheManager()!=null){
getCacheManager().shutdown();
logger.info("CacheManager was shutdown...");
}
}
/**
* 测试用
* @param cache
*/
//打印方法1,为了测试用
@SuppressWarnings("unused")
public static void printCache(Cache cache){
logger.info("缓存状态: "+cache.getStatus().toString());
if(cache==null){
logger.info("cache is null,no print info.");
}else if(cache.getStatus().toString().equals(Status.STATUS_UNINITIALISED)){
logger.info("缓存状态: 未初始化"+cache.getStatus().toString());
}else if(cache.getStatus().toString().equals(Status.STATUS_SHUTDOWN)){
logger.info("缓存状态: 已关闭"+cache.getStatus().toString());
}else if(cache.getStatus().toString().trim().equals(Status.STATUS_ALIVE)){
System.out.println("进入缓存取数据");
if(cache.getKeys().size()==0){
logger.info(cache.getName()+" exits,but no value.");
}else{
for(int i=0;i<cache.getKeys().size();i++){
Object thekey=cache.getKeys().get(i);
Object thevalue=cache.get(thekey);
logger.info(cache.getName()+"--"+i+",key:"+thekey.toString()+",value:"+thevalue.toString());
}
}
}
}
//打印方法2,为了测试用
public static void printCacheByName(String cacheName){
if(cacheName==null||cacheName.trim().equals("")){
logger.info("cacheName is null,no print info.");
}else{
if(getCacheManager().getCache(cacheName.trim())!=null){
Cache cache=getCacheManager().getCache(cacheName.trim());
printCache(cache);
}else{
logger.info(cacheName+" --null");
}
}
}
public static void main(String[] sdfsf){
Cache cache1=EhCacheManager.getCacheByName(EhCacheManager.CACHE_MYCOMMONCACHE);
printCache(cache1);
EhCacheManager.putElementToCache(EhCacheManager.CACHE_MYCOMMONCACHE, "111", "111haah");
EhCacheManager.putElementToCache(EhCacheManager.CACHE_MYCOMMONCACHE, "222", "222haah");
EhCacheManager.putElementToCache(EhCacheManager.CACHE_MYCOMMONCACHE, "333", "333haah");
printCache(cache1);
EhCacheManager.putElementToCache(EhCacheManager.CACHE_MYCOMMONCACHE, "111", "111的新值。");
logger.info(EhCacheManager.getElementValueFromCache(EhCacheManager.CACHE_MYCOMMONCACHE, "111"));
printCache(cache1);
clearAllFromCacheManager();
printCache(cache1);
removalAllFromCacheManager();
printCache(cache1);
shutdownCacheManager();
}
///上面是对缓存操作的Demo,实际使用逻辑需要改变 /
///以下是web环境下对字典表的缓存操作/
//得到字典表cache对象("cacheTest")
public Cache getMyCommonCache(){
Cache cache=null;
if(getCacheManager().getCache(EhCacheManager.CACHE_MYCOMMONCACHE)!=null){
cache=getCacheManager().getCache(EhCacheManager.CACHE_MYCOMMONCACHE);
}else{//如果缓存没有了,这里直接添加,因为在实际中我们不可能告诉应用没有了这个缓存就返回了。
//而是应该先去查数据,放入缓存,然后再从缓存中取数据。
//当然,如果缓存有数据,那就直接取数据就行了。
getCacheManager().addCache(EhCacheManager.CACHE_MYCOMMONCACHE);
}
return cache;
}
//从cacheTest缓存中获取字典表数据(这里只是简单的把所有值取出来了,实际应用可以更加细化)
public List<UserTest> getDictionaryListFromMyCommonCache(String codeNo){
codeNo=(codeNo==null||codeNo.trim().equals(""))?"":codeNo.trim();
List<UserTest> dictionaryList=null;
Cache cache=getMyCommonCache();//字典表公用缓存
Element element=null;
if(cache.get(EhCacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY)!=null){
element=cache.get(EhCacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY);
if(element.getObjectValue()==null){//值为空,需要从新添加到缓存
List<UserTest> userList=this.getQueryMsgTestDao().queryUserByName(codeNo);//查询
if(userList!=null&&userList.size()!=0){
MyCacheObject myCacheObject = new MyCacheObject(userList);
element=new Element((Serializable)EhCacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY,(Serializable)myCacheObject);
//java.io.NotSerializableException:
cache.put(element);
logger.info("缓存中的字典表元素为空,重新查询添加..");
}
dictionaryList=userList;
}else{//有值
MyCacheObject myObj=(MyCacheObject)element.getObjectValue();
dictionaryList=(List<UserTest>)myObj.getObject();
logger.info("缓存中存在字典表数据,直接获取到。");
}
}else{//获取Element空,需要从新添加到缓存
List<UserTest> userList=this.getQueryMsgTestDao().queryUserByName(codeNo);//查询
if(userList!=null&&userList.size()!=0){
MyCacheObject myCacheObject = new MyCacheObject(userList);
element=new Element((Serializable)EhCacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY,(Serializable)myCacheObject);
cache.put(element);
logger.info("缓存中的字典表元素为空,重新查询添加......");
}
dictionaryList=userList;
}
return dictionaryList;
}
/**
* 有时需要强制从数据库查询最新的实际数据,所以需要刷新缓存,保证数据的实时性。
* 这里的刷新是指把缓存中所有Element清除
*/
public void refreshDictionaryListInMyCommonCache(){
Cache cache=getMyCommonCache();//字典表公用缓存
Element element=null;
if(cache.get(EhCacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY)!=null){
for(int i=0;i<cache.getKeys().size();i++){
cache.remove(cache.getKeys().get(i));
}
}
//如果某些缓存刷新后需要马上填充,就可以像下面直接放数据
// if(this.getMyEhcacheDao().querydictionaryByCodeNo("")!=null){
// List list=this.getMyEhcacheDao().querydictionaryByCodeNo("");//查询
// MyCacheObject myCacheObject = new MyCacheObject(list);
// element=new Element((Serializable)MyEhcacheManager.ELEMENT_MYCOMMONCACHE_DICTIONARY,(Serializable)myCacheObject);
// cache.put(element);
// System.out.println("已经强制刷新字典表缓存。。。");
// }
System.out.println("已经强制清空字典表所有缓存。。。");
}
}