1.ehcache:百度百科这样解释的,EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。总的来说,他的出现就是减少对数据库的访问次数。从数据库查询出来的数据放到缓存中,以便下次调用,大大减少了 开销,性能也得到了提高。
特点:
l 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>
l 如果你的数据只是临时存放到缓存,减轻数据库压力,用默认值就很好
l 如果你的数据要在程序运行过程中一直被查询,则建议将设置为所有的元素被清除,一般用于数据字典。
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的值定死!(随机数)