SpringCache
1.原理图
2.SpringCache缓存实现(此项目是通过mybatis-ssm项目复制得来的)
(1).创建一个spring-cache.xml配置文件
<?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"> <cache:annotation-driven cache-manager="cacheManager"/><!--需要启用SpringCache--> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"><!--id="news"就是在业务层里面进行缓存具体操作时使用的名称--> <bean id="news" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"/> </property> </bean> </beans>
(2).如果要想让缓存配置生效。则一定要在spring-base.xml配置文件里面追加配置项
<import resource="spring-cache.xml"/><!--将cache配置文件导入spring-base.xml配置文件即可-->
(3).修改业务层接口。这里以INewsService接口为例
public interface INewsService{//下面的news就是上面的那个"id="news""
@Cacheable(cacheNames="news")//调用此方法就会触发id缓存
public News get(long id);或
@Cacheable(cacheNames = "news",condition = "#id<10",unless = "#result==null" )//调用此方法id<10就会触发id缓存,id>10则不再触发缓存
public News get(long id) ;
@Cacheable(cacheNames = "news",key = "#id")//此时会认为这两个参数同时满足的时候才会进行缓存数据的加载(此时如果没有设置"key",那么就表示
缓存的key就是两个参数的整合),但是很多时候未必对所有的参数都需要设置缓存,所以在注解里面加了一个key的属性对缓存做出了一个标记。定义key之后,在其
它的查询方法里面,只要根据id进行查询的时候都会触发此缓存。
public News get(long id,String title);
@Cacheable(cacheNames = "news",key = "#id",sync = true)//"sync"为同步标记,此时由于配置了"sync"属性,所以在进行并发访问的时候
只会由一个线程负责缓存数据的添加
public News get(long id,String title);
}
3.缓存更新
1.缓存更新用@CachePut注解控制
2.因为每次注解之前都要注解cacheNames="news",也可以在接口类上面直接使用@CacheConfig(cacheNames="news")进行了缓存信息的统一配置处理
3.@CachePut(key="#vo.nid",unless="#result==null")
public News update(News vo);//一定要返回新的News对象实例
4.缓存清除
缓存清除用 @CacheEvict
public boolean delete(long id);
5.多级缓存如果既想保存id的缓存又想保存title的缓存,这样操作的前提是这两个字段都没有重复的数据内容
@Cacheable(unless="#result==null") public News get(long id); @Cacheable(unless="#result==null") public News get(String title); 修改两个参数的get()方法定义,在此操作之中使用多级缓存设置(当前的操作表示对id和title都进行缓存设置): @Cacheable(cacheable={ @Cacheable(key="#id"), @Cacheable(key="#title") }) public News get(long id,String title); 在进行缓存更新的时候也可以使用多级缓存设置 @Cacheable(put={ @Cacheput(key="#vo.nid",unless="#result==null") @Cacheput(key="#vo.title",unless="#result==null") }) public News update(News vo);
说明:在上面的SpringCache都是基于ConcurrentHashMap的操作实现的,但是这样的操作只是在java层次上的实现,而从行业之内使用比较广泛的缓存有两类组件:单机缓存组件(EHCache)和分布式缓存组件(Redis)。
6.SpringCache整合EhCache缓存组件
(1).导入依赖包
<!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.6</version> </dependency>
(2).在"src/main/resources/"目录下创建一个ehcache.xml配置文件
<?xml version="1.1" encoding="UTF-8"?> <ehcache name="springcache"> 随意定义的缓存的管理名称 <diskStore path="java.io.tmpdir"/>磁盘上的临时存储路径(环境属性) <defaultCache 定义默认的最多的元素个数 maxElementsInMemory="2000" 允许缓存的最多的元素个数 eternal="true" 允许缓存的内容自动失效 timeToIdleSeconds="120" 设置缓存的失效时间 timeToLiveSeconds="120" 设置缓存的存活时间 overflowDisk="true"/> 当内存不足时,允许将缓存写入到磁盘 <cache name="news" maxElementsInMemory="2000" 允许缓存的最多的元素个数 eternal="false" 允许缓存的内容自动失效 timeToIdleSeconds="300" 设置缓存的失效时间 timeToLiveSeconds="0" 设置缓存的存活时间 overflowDisk="true"/> 当内存不足时,允许将缓存写入到磁盘 < /cache> /ehcache>
(3).如果想使用ehcache缓存组件就必须在spring-cache.xml配置文件中进行缓存的相关定义
<cache:annotation-driven cache-manager="cacheManager"/> <!-- 需要启用SpringCache -->
<bean id="cacheManagerFactoryBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/><!--配置文件-->
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" >
<property name="eacheManager" ref="cacheManagerFactoryBean"/>
</bean>
注:这个时候只需要修改当前的配置文件,就可以实现项目之中的缓存管理组件的更换。
7.整合Redis分布式缓存
• 在模块之中引入lettuce,springdataredis,commons-pool2等相关的依赖库
• 在src/main/profiles/dev/config/redis.properties配置文件,dev为源代码目录。
redis.host=redis-server//redis数据库连接的主机名称或ip地址 redis.port=6379 //连接端口 redis.auth=hellolee //认证信息 redis.database=0 //数据库的索引编号 redis.pool.maxTotal=10 //连接池最大的总连接数量 redis.pool.maxIdle=5 //连接池维持的最大连接数量 redis.pool.minIdle=3 //连接池维持的最小的连接数量 redis.pool.testOnBorrow=true //所有的连接测试后返回
• 由于Lettuce组件需要基于构建模式进行代码的实现,所以本次直接利用配置类的形式进行Redis的连接配置,在这个配置里面重点的配置项在与使用的"RedisTemplate<String,Object>";
• 修改spring-base.xml配置文件,追加新的扫描路径:<context:component-scan base-package="com.yootk.ssm.service,com.yootk.ssm.dao,com.yootk.ssm.config"/>
• 在SpringCache之中并没有提供专属的Redis缓存实现,所以开发者需要自行进行Redis的缓存的具体操作,而这个具体的操作一定要实现Cache接口。
@Bean("redisTemplate")//将原来的getRedisTempalate方法改成现在这个 public RedisTemplate getRedisTempalate( @Autowired RedisConnectionFactory connectionFactory ) { RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>() ; redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); // 数据的key通过字符串存储 redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); // 保存的value为对象 redisTemplate.setHashKeySerializer(new StringRedisSerializer()); // 数据的key通过字符串存储 redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer()); // 保存的value为对象 return redisTemplate ; }
• 修改spring-cache.xml配置文件,使用新的RedisCache进行缓存管理。
<cache:annotation-driven cache-manager="cacheManager"/> <!-- 需要启用SpringCache --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches" ><!--配置文件--> <set> < bean class="com.yootk.cache.RedisCache" > <property name="name" ref="news"/> <property name="redisTemplate" ref="redisTemplate"/> </bean> </set> </property> </bean> 注:这个时候只需要修改当前的配置文件,就可以实现项目之中的缓存管理组件的更换。
在实际开发之中,这样的缓存的管理机制是当今项目所推荐采用的形式。