技术 随笔 框架 ssm 异常 SSM框架整合笔记(六)缓存配置Ehcache 程序员七平 2019-03-08 2024-12-15 前言 缓存(Caching)可以存储经常会用到的信息,在需要的时候,直接返回这些信息。Spring对缓存的支持有两种方式:1)注解驱动的缓存;2)XML声明的缓存;本文使用第二种方式来实际进行配置。
本文内容
缓存内容详解
配置Ehcache缓存
配置Mybatis Generator
缓存内容详解 使用@EnableCaching
和cache:annotation-driven/
的工作方式是相同的,都会创建一个切面并触发Spring缓存注解的切点。根据所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值。在启用注解驱动的缓存时,还声明了一个缓存管理器的bean。缓存管理器是Spring缓存抽象的核心,能够与多个流行的缓存实现进行集成。
如何启用缓存 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Configuration @EnableCaching public class CachingConfig { @Bean public CacheManager cacheManager () { return new ConcurrentMapCacheManager (); } }
XML方式配置方式如下
1 2 3 4 5 <cache:annotation-driven /> <bean id ="cacheManager" class ="org.springframework.cache.concurrent.ConcurrentMapCacheManager" />
ConcurrentMapCacheManager 使用 java.util.concurrent.ConcurrentHashMap 作为缓存存储,这个缓存存储是基于内存的,因此其生命周期是与应用关联的,不太适合于生产级别的大型企业级应用程序,因此有其他的缓存管理器方案可供使用。
配置缓存管理器 Spring中内置了如下几种缓存管理器实现:
SimpleCacheManager
NoOpCacheManager
ConcurrentMapCacheManager
CompositeCacheManager
EhCacheCacheManager …
SpringData提供的缓存管理器:
RedisCacheManager(来自于Spring Data Redis项目)
GemfireCacheManager(来自于Spring Data GemFire项目)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import net.sf.ehcache.CacheManager;import org.springframework.cache.annotation.EnableCaching;import org.springframework.cache.ehcache.EhCacheCacheManager;import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.ClassPathResource;@Configuration @EnableCaching public class CachingConfig { @Bean public EhCacheCacheManager cacheManager (CacheManager cm) { return new EhCacheCacheManager (cm); } @Bean public EhCacheManagerFactoryBean ehcache () { EhCacheManagerFactoryBean ehCacheFactoryBean = new EhCacheManagerFactoryBean (); ehCacheFactoryBean.setConfigLocation(new ClassPathResource ("" )); return ehCacheFactoryBean; } }
也可以通过CompositeCacheManager使用多个缓存管理器。
一、为方法添加注解支持缓存 以下注解如果放在单独的方法上时,注解所描述的缓存行为只作用于这个方法上,如果放在类级别,那么缓存行为就会应用到这个类的所有方法上。
注解
描述
@Cacheable
Spring在调用方法之前,首先应该在缓存中查找方法的返回值。如果这个值能够找到,就会返回缓存的值。否则,这个方法就会被调用,返回值就会放到缓存之中
@CachePut
Spring应该将方法的返回值放到缓存中,在方法的调用前并不会检查缓存,方法始终会被调用
@CacheEvict
Spring应该在缓存中清除一个或多个条目
@Caching
一个分组的注解,能够同时应用多个其他的缓存注解
填充缓存 @Cacheable和@CachePut注解都可以填充缓存。
示例:
1 2 3 4 @Cacheable(value="spittleCache") Spittle findOne (long id) { }
自定义缓存key 默认的缓存key要基于方法的参数来确定,参数是一个map,那么其缓存的key也是这个map,因此需要把默认的key改为map的key,而不是这个map,所以需要自定义缓存key。
Spring 提供了多个用来定义缓存规则的SpEL扩展
表达式
描述
#root.args
传递给缓存方法的参数,形式为数组
#root.caches
该方法执行时所对应的缓存,形式为数组
#root.target
目标对象
#root.targetClass
目标对象的类,是#root.target.class的简写形式
#root.method
缓存方法
#root.methodName
缓存方法的名字,是#root.method.name的简写形式
#result
方法调用的返回值(不能用在@Cacheable主街上)
#Argument
任意的方法参数名(如#argName)或参数索引(如#a0或#p0)
1 2 @Cacheable(value="spittleCache" key="#result.id") Spittle save (Spittle spittle) ;
条件化缓存
前面说的是通过为方法添加Spring的缓存注解,Spring就会围绕着这个方法创建一个缓存切面。条件化缓存是说将缓存功能关闭的一些场景。@Cacheable和@CachePut提供两个属性用以实现条件化缓存:unless和condition。如果unless属性的SpEL表达式计算结果为true,缓存方法返回的数据不会放到缓存中。如果condition属性的SpEL表达式计算结果为false,对于这个方法缓存就会被禁用掉。
unless属性只能阻止将对象放进缓存,但是在这个方法调用的时候,依然会去缓存中进行查找。如果condition的表达式计算结果为false,这个方法调用时,缓存是被禁用的,也就不会去缓存中查找,返回值也不会放进缓存中。
例:
1 2 3 4 5 6 7 8 9 10 @Cacheable(value="spittleCache" unless="#result.message.contains('NoCache')") Spittle findOne (long id) ; @Cacheable(value="spittleCache" unless="#result.message.contains('NoCache')" condition="#id >= 10") Spittle findOne (long id) ;
移除缓存条目 @CacheEvict不会往缓存中添加任何东西,且如果带有该注解的方法被调用的话,缓存中的一个或更多的条目会被移除。
1 2 @CacheEvict("spittleCache") void remove (long spittleId) ;
注意:@Cacheable和@CacheEvict必须应用在返回值非void的方法上,@CacheEvict可以放在任意的方法上,甚至void方法
@Cacheable注解的属性,指定哪些缓存条目应该被移除掉
属性
类型
描述
value
String[]
要使用的缓存名称
key
String
SpEL表达式,用来计算自定义的缓存key
condition
String
SpEL表达式,如果得到的值是false的话,缓存不会应用到方法调用上
allEntries
boolean
如果为true的话,特定缓存的所有条目都会被移除掉
beforeInvoication
boolean
如果为true的话,在方法调用之前移除条目,如果为false(默认值)的话,在方法成功调用之后再移除条目
二、使用XML声明缓存
元素
描述
<cache:annotation-driven>
启用注解驱动的缓存,等同于Java配置中的@EnableCaching
<cache:advice>
定义缓存通知。结合<aop:advisor>,将通知应用到切点上
<cache:caching>
在缓存通知中定义缓存规则
<cache:cacheable>
指明某个方法要进行缓存。等同于@Cacheable注解
<cache:cache-put>
指明某个方法要填充缓存,但不会考虑缓存中时候已有匹配的值,等同于@CachePut注解
<cache:cache-evict>
指明某个方法要从缓存中移除一项或多项,等同于@CacheEvict注解
填充缓存 1 2 3 <cache:cacheable > <cache:cacheable cache ="spittleCache" method ="findRecent" />
自定义缓存key 1 <cache:cache-put cache ="spittleCache" method ="save" key ="#result.id" />
移除缓存条目 1 <cache:cache-evict cache ="spittleCache" method ="remove" />
配置Ehcache缓存 Ehcache的主要特性有:
快速、精干,简单;
多种缓存策略;
缓存数据有两级:内存和磁盘,因此无需担心容量问题;
缓存数据会在虚拟机重启的过程中写入磁盘;
可以通过RMI、可插入API等方式进行分布式缓存;
具有缓存和缓存管理器的侦听借口;
支持多缓存管理器实例,以及一个实例的多个缓存区域;
提供Hibernate 的缓存实现;
上面的声明应该改为以下方式
pom.xml添加配置
1 2 3 4 5 6 7 8 9 10 11 <dependency > <groupId > org.ehcache</groupId > <artifactId > ehcache</artifactId > <version > 3.6.3</version > </dependency > <dependency > <groupId > org.mybatis.caches</groupId > <artifactId > mybatis-ehcache</artifactId > <version > 1.3.5</version > </dependency >
添加spring-ehcache.xml并配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?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: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/cache http://www.springframework.org/schema/cache/spring-cache.xsd" > <description > Ehcache缓存配置文件</description > <cache:annotation-driven cache-manager ="cacheManager" /> <bean id ="ehcache" class ="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" > <property name ="configLocation" value ="classpath:config/ehcache.xml" /> <property name ="shared" value ="true" /> </bean > <bean id ="cacheManager" class ="org.springframework.cache.ehcache.EhCacheCacheManager" > <property name ="cacheManager" ref ="ehcache" /> </bean > </beans >
spring-config.xml中添加配置
1 2 <import resource ="classpath:config/spring-ehcache.xml" />
在resources/config文件夹下添加ehcache.xml并添加配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version="1.0" encoding="UTF-8" ?> <ehcache name ="ehcache" updateCheck ="false" > <diskStore path ="java.io.tmpdir/ehcache" /> <defaultCache maxEntriesLocalHeap ="10000" eternal ="false" overflowToDisk ="true" timeToIdleSeconds ="100" timeToLiveSeconds ="120" diskPersistent ="false" maxEntriesLocalDisk ="10000000" diskExpiryThreadIntervalSeconds ="120" memoryStoreEvictionPolicy ="LRU" > </defaultCache > <cache name ="systemCatch" maxElementsInMemory ="1000" eternal ="false" timeToIdleSeconds ="10" timeToLiveSeconds ="30" overflowToDisk ="true" diskPersistent ="false" memoryStoreEvictionPolicy ="LRU" /> </ehcache >
这三个文件配置完了之后,Ehcache的配置也就完成了,下面我们说一下测试的方法。
测试缓存配置 SysMenuServiceImpl.java 中添加如下代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Service public class SysMenuServiceImpl extends BaseService <SysMenu> implements SysMenuService { private static final Logger logger = Logger.getLogger(SysMenuServiceImpl.class); @Autowired SysMenuDao sysMenuDao; @Cacheable(value="systemCatch", key="'SysMenuServiceImpl.systemCatch'") @Override public List<SysMenu> findMenuList (SysMenu sysMenu) { List<SysMenu> sysMenus = sysMenuDao.queryMenuList(sysMenu); Long timestamp = System.currentTimeMillis(); logger.error("timestamp>>>>>>>>>>>>>>>>>>>>>>>>>" + timestamp); return sysMenus; } }
SysMenuController.java 中添加如下代码,观察start 和 end方法之间会不会打印sql以及中间打印时间的日志。
1 2 3 4 5 6 7 8 9 10 @RequestMapping(value = "sysMenuList") @ResponseBody public List<SysMenu> getSysMenuList () { SysMenu sysMenu = new SysMenu (); sysMenu.setMenuId("01" ); logger.info("-----------------------------------------------findMenuList start-----------------------------------" ); List<SysMenu> menuList = sysMenuService.findMenuList(sysMenu); logger.info("-----------------------------------------------findMenuList end-----------------------------------" ); return menuList; }
具体效果如下:
问题处理 问题一 1 [ContainerBackgroundProcessor[StandardEngine[Catalina]]] org.apache.catalina.webresources.Cache.backgroundProcess The background cache eviction process was unable to free [10] percent of the cache for Context [/lx_note] - consider increasing the maximum size of the cache. After eviction approximately [9,686] KB of data remained in the cache.
并没有报错,只是Console打印出来信息,提示不能自动释放10%的缓存,需要调大cache的最大容量;
解决方法: Tomcat8 的conf/目录下的context.xml添加配置,默认大小是10240即10M,这边给调大了10倍。
1 <Resources cachingAllowed="true" cacheMaxSize="102400" />
相关文章推荐
源码下载 该项目持续更新中,会在代码以及该文档里面详细注释和介绍。项目托管在码云
开源平台上,持续更新项目源码链接:https://gitee.com/nelucifer/ssm-note ,点击克隆/下载
获取该项目。