目录
1 概述
2?@Cacheable注解使用详细介绍
? ? ? ? 2.1 @Cacheable注解使用
????????2.2??Cacheable?注解的属性
1 概述
? ? ? ? Spring高版本引入了cache的注解技术。该技术是一种规范。Redis的cache技术,底层使用的是Spring Data Redis。cache技术的使用需要掌握的有@EnableCaching、@Cacheable、@CacheEvict、@Caching、@CacheConfig注解的使用,这些注解支持SpringSPEL表达式方式。
今天先了解@Cacheable注解。
2?@Cacheable注解使用详细介绍
? ? ? ? 2.1 @Cacheable注解使用
步骤一:cacheConfig配置类
package com.liubujun.redis_springboot.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: liubujun
* @Date: 2022/2/5 15:21
*/
@Configuration
@EnableCaching
public class CacheConfig {
/**
* CacheManager为一个接口,RedisCacheManager为该接口的实现
* redisConnectionFactory 连接工厂
* cacheDefaults 默认配置
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
RedisCacheManager redisCacheManager = RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(defaultCacheConfig(10000))
.withInitialCacheConfigurations(initCacheConfigMap())
.transactionAware()
.build();
return redisCacheManager;
}
/**
* 默认配置中进行了序列化的配置
* @param second
* @return
*/
private RedisCacheConfiguration defaultCacheConfig(Integer second) {
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//配置序列化 解决乱码的问题
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(second))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
return config;
}
/**
* 针对不同的redis的key 有不同的过期时间
* @return
*/
private Map<String,RedisCacheConfiguration> initCacheConfigMap() {
Map<String,RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("User",this.defaultCacheConfig(1000));
configMap.put("User1",this.defaultCacheConfig(1000));
configMap.put("User2",this.defaultCacheConfig(1000));
configMap.put("User3",this.defaultCacheConfig(1000));
return configMap;
}
}
步骤二:application.properties文件配置redis的参数
#redis服务器地址(自己redis所在主机地址)
spring.redis.host=*******
#redis服务器连接端口
spring.redis.port=6379
#redis数据库索引(默认是0)
spring.redis.database=0
#连接超时时间
spring.redis.timeout=1800000
#连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=20
#最大阻塞等待时间(负数表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
#连接池中最大空闲连接
spring.redis.lettuce.pool.max-idle=5
#连接池中最小空闲连接
spring.redis.lettuce.pool.min-idle=0
步骤三:测试类编写
package com.liubujun.redis_springboot.controller;
import com.liubujun.redis_springboot.entity.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @Author: liubujun
* @Date: 2022/2/2 16:17
*/
@RestController
@RequestMapping("/redisTest")
public class TestController {
@GetMapping("/cache/{id}")
@Cacheable(cacheNames = "User",key = "#id") //此时缓存中的key为id,value为查询出来的数据(#id就表示取出参数id的值作为key)
public User findUserById(@PathVariable("id") Integer id){
User user = new User();
user.setId(id);
user.setName("测试:springBooth中Cache"+id+"查询时间戳"+System.currentTimeMillis());
System.out.println("模拟数据库查询数据id:"+id+"name:"+user.getName());
return user;
}
}
步骤四:浏览器访问
相同id连续两次访问接口
?
控制台只有一句输出语句:?
?
?redis客户端中存储的值:
?
我将用相同的id连续访问两次,控制台只有一句输出语句,那么就说明:第一次访问走了代码逻辑并且将返回结果放入了cacheable中。第二次直接从缓存中取出的数据,没有走代码逻辑。体检了cacheable的作用。
总结:?@Cacheable ?注解可以将运行结果缓存,以后查询相同的数据,直接从缓存中调取,不需要调用方法,换言之:在方法上加了@Cacheable ?注解后,每次调用该方法,都会先检查缓存中有没有相同的key,如果有直接从缓存中获取,没有再调用具体代码逻辑。
????????2.2??Cacheable ?注解的属性
-
cacheNames/value ?:用来指定缓存组件的名字 -
key ?:缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写) -
keyGenerator ?:key 的生成器。 key 和 keyGenerator 二选一使用 -
cacheManager ?:可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。 -
condition ?:可以用来指定符合条件的情况下才缓存 -
unless ?:否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过?#result ?获取方法结果) -
sync ?:是否使用异步模式。
1)cacheNames/value ?:
用来指定缓存组件的名字,将方法的返回结果放在哪个缓存中,可以是数组的方式
@GetMapping("/cache/{id}")
@Cacheable(cacheNames = "User") //也可以这样写@Cacheable(cacheNames {"User","Users"})
public User findUserByIds(@PathVariable("id") Integer id){
User user = new User();
user.setId(id);
user.setName("测试:springBooth中Cache"+id+"查询时间戳"+System.currentTimeMillis());
System.out.println("模拟数据库查询数据id:"+id+"name:"+user.getName());
return user;
}
2)key ?:
缓存数据时使用的key。默认使用的是方法参数的值,也可以使用spEL表达式编写
@GetMapping("/cache/{id}")
@Cacheable(cacheNames = "User",key = "#root.methodName+'[' + #id + ']'") //这时如果传入的id为500,那么key=findUserById[500]
public User findUserById(@PathVariable("id") Integer id){
User user = new User();
return user;
}
3)keyGenerator ?:
key的生成器,可以用自己指定的生成器去生成key
4)condition ?:
符合条件的情况下才进行缓存
@GetMapping("/cache/{id}")
@Cacheable(cacheNames = "User",condition = "#id >1 ") //这里表示id值大于1时才进行缓存
public User findUserByIds(@PathVariable("id") Integer id){
User user = new User();
return user;
}
5)unless ?:
否定缓存,当unless指定的条件为true时,方法的返回值不会被缓存
@GetMapping("/cache/{id}")
@Cacheable(cacheNames = "User",unless = "#id >1 ") //这里表示id值大于1时不会进行缓存
public User findUserByIds(@PathVariable("id") Integer id){
User user = new User();
return user;
}
6)sync ?:
是否使用异步模式,默认是方法执行完后,以同步的方式将方法返回的结果存在缓存中
参考博客:SpringBoot 缓存之 @Cacheable 详细介绍_勇往直前的专栏-CSDN博客_@cacheable
|