首页 > 技术文章 > ehcache的基本使用及Spring整合

lichangyun 2018-02-07 09:33 原文

1.ehcache:百度百科这样解释的,EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。总的来说,他的出现就是减少对数据库的访问次数。从数据库查询出来的数据放到缓存中,以便下次调用,大大减少了 开销,性能也得到了提高。

特点:

Java界最出名的缓存框架,主要用于单机缓存,速度很快。

 

l 进程级别的缓存,多个线程可共享一个缓存数据。

 

其实现方式如下图所示:

2.简单的解释一下ehcache的核心配置文件

 1  <!-- 硬盘上缓存的临时目录 -->
 2     <diskStore path="java.io.tmpdir"/>
 3     <!-- 
 4     maxElementsInMemory:内存中最大存放的元素的个数
 5     eternal:是否永生,默认是false
 6     timeToIdleSeconds:发呆闲置的时间,超过该时间,被清除,单位秒
 7     timeToLiveSeconds:存活的事件,超过该时间被清除
 8     maxElementsOnDisk:如果内存满了,溢出到硬盘上的临时目录中的存放的元素的个数
 9     diskExpiryThreadIntervalSeconds:轮询时间,巡视组
10     memoryStoreEvictionPolicy:内存对象的清理策略,如果满了,怎么办?
11     策略有三个:LRU、LFU、FIFO
12     LRU:最少使用被清理,次数
13     LFU:时间,闲置最长的时间
14     FIFO:管道策略,先进先出
15      -->
16     <defaultCache
17             maxElementsInMemory="10000"
18             eternal="false"
19             timeToIdleSeconds="120"
20             timeToLiveSeconds="120"
21             maxElementsOnDisk="10000000"
22             diskExpiryThreadIntervalSeconds="120"
23             memoryStoreEvictionPolicy="LRU">
24         <persistence strategy="localTempSwap"/>
25     </defaultCache>
View Code

如果你的数据只是临时存放到缓存,减轻数据库压力,用默认值就很好

如果你的数据要在程序运行过程中一直被查询,则建议将设置为所有的元素被清除,一般用于数据字典。

 

3.ehcache中的缓存注解

@Cacheable和@CacheEvict来对缓存进行操作

@Cacheable:将方法的返回值放入到缓存中

@CacheEvict:负责清除缓存

 

4.下面与Spring整合的案列

需求:将菜单数据放入Ehcache中。

4.1.引入坐标

<!-- ehcache的缓存框架 -->
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache-core</artifactId>
			<version>2.6.10</version>
		</dependency>
		<!-- spring整合第三方框架的 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>

  

4.2.编写配置文件(ehcache文件)

<!-- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
 --><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <!-- 磁盘上的缓存的临时目录 ,默认是系统的临时目录,也可以手动指定一个目录-->
    <diskStore path="java.io.tmpdir"/>
    <!-- 默认的缓存区域的默认策略 -->
    <!--
    maxElementsInMemory:内存中元素最大存放的个数
    eternal:缓存的对象是否永生不死。一般都是false。
    timeToIdleSeconds:发呆的时间,多长时间不用,就干掉,秒
    timeToLiveSeconds:存活的时间,活够了就干掉,秒
    maxElementsOnDisk:硬盘上最大存放的元素的个数,如果内存10000个满了,就往硬盘上存。
    memoryStoreEvictionPolicy:内存中存储和销毁元素的策略:默认使用LRU,解决的是缓存元素满了怎么办。
      策略有三个:LRU、LFU、FIFO
    LRU:最少使用被清理,次数
    LFU:时间,闲置最长的时间
    FIFO:管道策略,先进先出
     -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
    <!-- Spring整合的菜单缓存 -->
    <cache name="bos_menu_cache"
           maxElementsInMemory="10000"
           eternal="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           maxElementsOnDisk="10000000"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </cache>

  

4.3.Spring整合encache配置文件(需要引入ehcache文件)

<?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:context="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="
                http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/cache
                http://www.springframework.org/schema/cache/spring-cache.xsd">
    <!-- 配置ehcache的对象EhCacheManager -->
    <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <!-- 注入ehcache核心配置文件的位置  可以不配置,默认找类路径下的ehcache.xml -->
        <property name="configLocation" value="classpath:ehcache.xml" />
    </bean>
    <!-- Spring整合Ehache -->
    <!-- Spring的平台缓存管理器 -->
    <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
        <!-- 注入ehcache的对象 -->
        <property name="cacheManager" ref="ehCacheManager"></property>
    </bean>
    <!-- spring的缓存注解驱动 -->
    <cache:annotation-driven cache-manager ="springCacheManager" />
</beans>

  

4.4.在需要操作缓存数据的方法上添加注解

package cn.bos.service.impl.system;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.bos.dao.system.MenuRepository;
import cn.bos.domain.system.Menu;
import cn.bos.domain.system.User;
import cn.bos.service.system.MenuService;


@Service("menuService")
@Transactional
public class MenuServiceImpl implements MenuService{

	@Autowired
	private MenuRepository menuRepository;
	
	@Override
	public List<Menu> menu_list() {
		
		return menuRepository.findAll();
	}

	@Override
	//清除所有的缓存
	@CacheEvict(value="bos_menu_cache",allEntries=true)
	public void menu_add(Menu model) {
		
		if(model.getParentMenu()!=null&&model.getParentMenu().getId()==null){
			model.setParentMenu(null);
		}
		
		menuRepository.save(model);
	}

	@Override
	//@Cacheable(value="bos_menu_cache")方法的结果放到缓存中
//	使用用户的标号作为缓存的key
	@Cacheable(value="bos_menu_cache",key="#user.id")
	public List<Menu> findMenuByUser(User user) {
//	管理员 所有菜单
		if("admin".equalsIgnoreCase(user.getUsername())){
			return menuRepository.findByOrderByPriority();
		}else{
//			普通用户(显示部分菜单)
			return menuRepository.findByUser(user);
		}
	}
}

  

注意:实体类中的序列化问题:

序列化的id,用来作为序列化和反序列化的唯一标识,默认的值是根据类的内容计算出来,如果类的内容发生变化,则值会变,例如:反序列化之前,将类改变内容了,那么反序列化将会失败。因此,为了保障反序列化成功,一般将该id的值定死!(随机数)

 

 

推荐阅读