一、为什么使用注解来操作redis缓存
二、使用缓存注解的具体方式
三、如何替换缓存错误的处理
一般如果我们想把一个对象添加到redis缓存当中,都会写这样的一段代码
@Autowired
private RedisUtil redisUtil;
redisInstance=redisUtil.get("test");
if(redisInstance != null){
redisInstance=new String();
}
redisUtil.add("test",redisInstance);
但是其实获取缓存的对象,判断对象是否为空,最后把对象放到缓存当中这样的操作对于不同的缓存操作都是一样的,那么通过使用注解的方式就可以把这么一段重复的代码抽离出来,减少重复代码。使用注解还有一个好处就是可拔插,不使用的时候,直接拿掉注解就可以了,不会影响原来的业务逻辑。更换使用的缓存方式也是,不需要替换缓存的实现方式。只需要把启用缓存注解的配置放到别的类型的缓存中即可。
前提是你已经引入了redis,没有的话可以在我的另一篇博客中看到https://mp.csdn.net/postedit/88782643
1、添加依赖
org.springframework.boot
spring-boot-starter-cache
2、设置启用缓存配置的设置
在redis的配置类RedisConfig.java里面添加
@EnableCaching
3、具体注解
主要的注解是,@Cacheable 、@CachePut、@CacheEvict
@Cacheable就是用来替换我们原来的判空,查询缓存并返回的操作;@CachePut则是每次都会执行方法,其实只是有一个存入缓存的操作(只是“put”);@CacheEvict 是用来清空缓存的。
三个注解都可以用到方法上和类上面使用,看注解的定义就可以明白。
4、代码实例
@Cacheable(value = "userBean",key = "#userId",condition="#userId>0")
public Optional getUserById(Integer userId) {
return userRepository.findById(userId);
}
@CacheEvict(value = "userBean",key = "#userId")
public void deleteUser(Integer userId) {
userRepository.deleteById(userId);
}
存入redis中的
除了以上的这些内容,缓存的注解还支持指定指定keyGenerator、cacheManager、sync等。同样,你也可以自定义注解,并使用上以上的这些注解,自己去实现一些特殊的需求,例如日志打印等,这些内容就不在这里展开来讲了。
思考一下,如果此时redis宕机了会怎样?
结果是,会直接抛出异常。但是其实我们希望的是,如果redis发生问题了,最终还是希望请求能够进入到数据库当中,那么,怎么实现呢?答案是重写注解支持的errorHandler方法
具体实现:
package com.example.config;
import com.example.Util.FastJsonSerializerForRedis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
Logger log= LoggerFactory.getLogger(RedisConfig.class);
@Override
public CacheErrorHandler errorHandler() {
CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
RedisException(exception, key);
}
@Override
public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
RedisException(exception, key);
}
@Override
public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
RedisException(exception, key);
}
@Override
public void handleCacheClearError(RuntimeException exception, Cache cache) {
RedisException(exception, null);
}
};
return cacheErrorHandler;
}
protected void RedisException(Exception exception, Object key){
log.error("redis异常:key=[{}], exception={}", key, exception.getMessage());
}
}
但是这样做要在application.properties里设置spring.redis.lettuce.pool.max-wait(redis拿不到链接的最长等待时间)这个属性值不能太大,越大请求的接口的时间会越长。
总结,本文简单讲述了如何引入注解操作redis,自定义注解操作的异常处理,保证redis链接不上时可以去访问数据库。文中若有疏漏之处请指出,以上。