#SpringBoot缓存注解@Cachable实现Redis缓存操作
方法1 直接操作RedisTemplate缓存数据
方法2 在方法上加@Cacheable注解来缓存数据(这里只讲该方法)
pom.xml引入Redis的starter,容器中默认保存的是RedisCacheManager。RedisCacheManager帮我们创建RedisCache,通过RedisCache操作Redis缓存数据。默认保存数据k/v 都是Object,使用默认的JDK序列化器。
org.springframework.boot
spring-boot-starter-data-redis
引入注解@EnableCaching,增加CacheManager配置。实现缓存自定义序列化和设置过期时间20s。
设置序列化后返回的是新的RedisCacheConfiguration。
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@Configuration
@EnableCaching
public class RedisConfig
{
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory)
{
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
Jackson2JsonRedisSerializer
@RestController
public class RedisController
{
@RequestMapping(value="cache/{id}")
public void cache(@PathVariable String id)
{
System.out.println("【Controll】cache---" + id);
this.redisService.cache(id);
}
@RequestMapping(value = "/addcache/{id}")
public boolean add(@PathVariable String id) {
Usr usr = new Usr();
usr.id = id;
usr.name = "Lyndon-" +id;
usr.pwd = "123";
this.redisService.addCache(usr);
return true;
}
@RequestMapping(value = "/delcache/{id}")
public void delByUuid(@PathVariable String id) {
this.redisService.delCache(id);
}
}
缓存注解在业务层
RedisService、RedisServiceImpl实现类
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
@Service
public class RedisServiceImpl implements RedisService
{
static final String REDIS_VALUE = "user-";
@Override
@Cacheable(value = REDIS_VALUE, key = "getArgs()[0]") // 结果可缓存
public User cache(String id){
User user = new User();
user.setId(id);
user.setName("Lyndon-" + id);
user.setPwd("123456");
System.out.println("【SERVICE】cache:" + user);
return user;
}
@Override
@CachePut(value = REDIS_VALUE, key = "getArgs()[0].id") //加入缓存
public Usr addCache(String id)
{
User user = new User();
user.id = id;
// this.redisTemplate.opsForSet().add(id, user);
System.out.println("【SERVICE】add cache:" + user);
return user;
}
@Override
@CacheEvict(value = REDIS_VALUE, key = "getArgs()[0]") //删除缓存
public void delCache(String id) {
}
}
@Cacheable 在调用方法之前,先在缓存中查找方法的返回值,如果这个值能够找到,返回缓存的值。否则执行这个方法,将方法的返回值放到缓存之中。
spEL几种写法
@Cacheable(value = "user", key = "#root.method") //"user::public com.example.demo.User com.example.demo.UserServiceImpl.findcache(com.example.demo.User)"
@Cacheable(value = "user", key = "#root.method.name") //"user::findcache"
@Cacheable(value = "user", key = "#root.targetClass") // "user::class com.example.demo.UserServiceImpl"
@Cacheable(value = "user", key = "args[0]") //user对象
@Cacheable(value = "user", key = "args[0].id") //"user::1001", 相当于"#user.id"
@Cacheable(value = "user", key = "caches[0].name") //"user::user"
@Cacheable(value = "user", key = "#user.id") //"user::1001"
@Cacheable(value = {"user1","user2"}, key = "#pageIndex+'-'+(#pageIndex+#pageSize)")
@Cacheable(value = {"dept_list"}, key = "#pageIndex+'-'+(#pageIndex+#pageSize)") //分页查询加入缓存
public List queryDepts(String id, String name, int level, int pageIndex, int pageSize) {
return this.deptDao.queryDepts(id, name, level, pageIndex, pageSize);
}
192.168.236.128:6379> keys *
1) "dept_list::40-60"
2) "dept_list::20-40"
3) "dept_list::0-20"
@CachePut 根据方法的请求参数对其结果进行缓存
@CacheEvict 根据条件对缓存进行清空
当缓存的实体更新后,get到的仍是旧的缓存。这时候就需要清除相关联的缓存。方法就是提供一个空的接口方法,在该方法上添加@CacheEvict的注解。
(也可使用定时任务实现缓存的自动清除功能。)
@CacheConfig(cacheNames = “user”)//类级别的缓存注解,允许共享缓存名称
@Caching 组合使用多个操作缓存的注解 evict={}中是用@CacheEvict 、 put={}中是用@CachePut 、 cacheable={}中是用
执行三次查询:
第一次 进入Service方法,添加了值
第二次 不进入Service方法也得到了值
同理第三次
【Controll】cache:1001
【SERVICE】---User [id = 1001, name=Lyndon-1001, pwd=123456l]
【Controll]】cache:1001
【Controll]】cache:1001
【Controll]】cache:1001
[root@localhost Desktop]# redis-cli -c -h 192.168.236.128 -p 6379 -a 123456
192.168.236.128:6379> keys user-*
-> Redirected to slot [7252] located at 192.168.236.128:6382
1) "user-::1001"
# 序列化前
192.168.236.128:6382> get user-::1001
"\xac\xed\x00\x05sr\x00\x15com.example.demo.User\x00\x00\x00\x00\x00\x00\x00\x01\x02\x00\x05L\x00\x02idt\x00\x12Ljava/lang/String;L\x00\x05ltimet\x00\x10Ljava/util/Date;L\x00\x04nameq\x00~\x00\x01L\x00\x03pwdq\x00~\x00\x01L\x00\x05tokenq\x00~\x00\x01xpt\x00\x041001sr\x00\x0ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\b\x00\x00\x01m\x15\x84w\xd0xt\x00\x041001t\x00\x03123t\x00 7c86ab65f8394c0a8ba966f1ba53b04c"
# 序列化后
192.168.236.128:6382> get user-::1001
"[\"com.example.demo.User\",{\"id\":\"1001\",\"name\":\"1002\",\"pwd\":\"123\",\"ltime\":[\"java.util.Date\",1568024066000],\"token\":\"7c86ab65f8394c0a8ba966f1ba53b04c\"}]"
# 20秒后缓存消失
192.168.236.128:6382> get user-::1001
(nil)
两种方式各不相同,一种是直接当成数据库调用形式,一种是通过注解的形式。
(方法1登录注册适用于缓存session、token等用户登录信息;方法2适用于缓存查询结果)
当然各有长短板,所以可以说,两种方式可以在项目中结合使用,但是缓存的时候不要互串,比如使用第二种方式创建的缓存在第一种方式获取,后面维护起来很痛苦。
springboot与redis处理缓存
http://liweidan.cn/java/frame/spring-boot/2019/01/08/254/
springboot2.0自定义ReidsCacheManager的改变
https://www.jianshu.com/p/20366ecf12ce
Spring Boot之 Spring Boot + Cache + RedisTemplate整合
https://blog.csdn.net/jy02268879/article/details/83095559