Spring中使用ehcache缓存的方法及原理详解
作者:爱coding的同学
ehcache简介
为什么使用ehcache
(1)速度快。
(2)轻量,很小的jar包,Ehcache 2.2.3才668kb。
(3)和spring集成,通过注解就可以实现本地缓存,使用简单。
(4)具有很强的灵活性,提供了LRU、LFU和FIFO缓存淘汰算法,Ehcache 1.2引入了最近最少使用、最久未使用和先进先 出缓存淘汰算法, 构成了完整的缓存淘汰算法。
(5)提供内存和磁盘存储,Ehcache和大多数缓存解决方案一样,提供高性能的内存和磁盘存储。在VM重启后,持久化到 磁盘的存储可以复原数据。
使用案例
配置
pom.xml中添加ehcache依赖包
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.9.1</version> </dependency>
ehcache文件配置:
<?xml version="1.0" encoding="UTF-8"?> <ehcache updateCheck="false"> <diskStore path="java.io.tmpdir" /> <!-- 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" timeToIdleSeconds="60" timeToLiveSeconds="60" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> <cache name="applicationCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="150" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="1" /> <cache name="indexCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="600" overflowToDisk="false" diskPersistent="false" diskExpiryThreadIntervalSeconds="1" /> </ehcache>
spring文件中的配置
<cache:annotation-driven cache-manager="ehcacheManager"/> <!-- cacheManager工厂类,指定ehcache.xml的位置 --> <beans:bean id="ehcacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <beans:property name="configLocation" value="classpath:config/ehcache.xml" /> </beans:bean> <!-- 声明cacheManager --> <beans:bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <beans:property name="cacheManager" ref="ehcacheManagerFactory" /> <beans:property name="transactionAware" value="true" /> </beans:bean>
此处的transactionAware表示是否事务环绕的,如果值是true,则如果事务回滚,缓存也回滚,默认false。
项目中的使用
例子,通过简单的配置即可实现缓存效果
@Override @Cacheable("applicationCache") public Map<String, Object> getAppDetailById(long appId) { byte[] app = redisTemplate.getRaw(String.format(CacheKeys.APP_DETAIL_BY_ID, appId)); if (null == app) { return Collections.EMPTY_MAP; } try { return CompressUtil.deCompress(app, appId); } catch (IOException t) { throw new FlymeTVServiceException(Errors.ServiceErrors.DE_COMPRESS_ERROR, new Object[] { "appId:" + appId }); } } @Cacheable(value = "categoryCache", key = "#categoryId + #sortType + #start + #max") @Override public MultiPage<Map<String, Object>> getCategoryApps(int categoryId, int sortType, int start, int max) { MultiPage<Map<String, Object>> result = new MultiPage<Map<String, Object>>(); String key = String.format(CacheKeys.CATEGORY_APPS, categoryId, sortType); List<String> appIds = redisTemplate.lrange(key, start, max + BACKUP_APP_SIZE); ..... return result; }
注解接口介绍如下:
public @interface Cacheable { //缓存的名字,可以把数据写到多个缓存 String[] value(); //缓存key,如果不指定将使用默认的KeyGenerator生成 String key() default ""; //满足缓存条件的数据才会放入缓存,condition在调用方法之前和之后都会判断 String condition() default ""; //用于否决缓存更新的,不像condition,该表达只在方法执行之后判断,此时可以拿到返回值result进行判断了 String unless() default ""; }
例子,java代码如下
@Cacheable(value = "user", key = "#id", condition = "#id lt 10") public User conditionFindById(final Long id)
根据运行流程,如下@Cacheable将在执行方法之前( #result还拿不到返回值)判断condition,如果返回true,则查缓存。
Key生成器
如果在Cache注解上没有指定key的话@Cacheable(“applicationCache”),会使用KeyGenerator进行生成一个key: java代码
public interface KeyGenerator { Object generate(Object target, Method method, Object... params); }
默认提供了DefaultKeyGenerator生成器
public Object generate(Object target, Method method, Object[] params) { if (params.length == 1) { return params[0] == null ? Integer.valueOf(53) : params[0]; } if (params.length == 0) { return Integer.valueOf(0); } int hashCode = 17; for (Object object : params) { hashCode = 31 * hashCode + (object == null ? 53 : object.hashCode()); } return Integer.valueOf(hashCode); }
新增和删除注解
@CachePut 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存: java代码
@CachePut(value = "user", key = "#user.id") public User save(User user) { users.add(user); return user; }
即调用该方法时,会把user.id作为key,返回值作为value放入缓存; 接口介绍,java代码:
public @interface CachePut { //缓存的名字,可以把数据写到多个缓存 String[] value(); //缓存key,如果不指定将使用默认的KeyGenerator生成 String key() default ""; //满足缓存条件的数据才会放入缓存,condition在调用方法之前和之后都会判断 String condition() default ""; //用于否决缓存更新的,不像condition,该表达只在方法执行之后判断,此时可以拿到返回值result进行判断了 String unless() default ""; }
例子,java代码
@CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") public User conditionSave2(final User user)
根据运行流程,如下@CachePut将在执行完方法后(#result就能拿到返回值了)判断unless,如果返回false,则放入缓存;(即跟condition相反)
到此这篇关于Spring中使用ehcache缓存的方法及原理详解的文章就介绍到这了,更多相关Spring使用ehcache缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!