SpringBoot2.x—SpringCache+Redis整合
SpringCache
SpringCache提供基本的Cache抽象,并没有具体的缓存能力,需要配合具体的缓存实现来完成,目前SpringCache支持redis、ehcache、simple(基于内存)等方式来实现缓存。
1.配置修改
1.1 maven配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
1.2 bootstrap配置
spring:
cache:
type: redis #指定用redis实现缓存
cache-names: user #在启动时创建缓存名称,即后面用到的cacheNames,多个名称用逗号分隔。
1.3 RedisConfig配置
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jdkSerializationRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jdkSerializationRedisSerializer);
template.afterPropertiesSet();
return template;
}
// 解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(redisCacheConfiguration)
.build();
return cacheManager;
}
@Bean
public KeyGenerator keyGenerator() {
/**
* target: 类
* method: 方法
* params: 方法参数
*/
return (target, method, params) -> {
//获取代理对象的最终目标对象
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getSimpleName()).append(":");
sb.append(method.getName()).append(":");
//调用SimpleKey的key生成器
Object key = SimpleKeyGenerator.generateKey(params);
return sb.append(key);
};
}
}
1.4 启动类添加下面的注解
@EnableCaching
2.Spring常用的缓存注解
@EnableCaching:开启缓存功能,一般使用在springboot的启动类或配置类上
@Cacheable:使用缓存。在方法执行前Spring先查看缓存中是否有数据,如果有数据,则直接返回缓存数据;没有则调用方法并将方法返回值放进缓存。
cacheNames:指定缓存空间的名称,不同缓存空间的数据是彼此隔离的。
key:同一个cacheNames中通过key区别不同的缓存。如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合,如:@CachePut(value = “demo”, key = “‘user’+#user.id”),字符串中spring表达式意外的字符串部分需要用单引号。SpringCache提供了与缓存相关的专用元数据,如target、methodMame、result、方法参数等,如:@CachePut(value = “demo”, key = “#result==null”)
keyGenrator:key的生成策略,SpringCache默认使用SimpleKeyGenerator,默认情况下将参数值作为键,但是可能会导致key重复出现,因此一般需要自定义key的生成策略
condition:condition是在调用方法之前判断条件,满足条件才缓存,如下:
@Cacheable(cacheNames=“book”, condition="#name.length() < 32")
unless:unless是在调用方法之后判断条件,如果SpEL条件成立,则不缓存【条件满足不缓存】如下:
@Cacheable(cacheNames = “hello”,unless="#result.id.contains(‘1’)" )
@CachePut:更新缓存,将方法的返回值放到缓存中
@CachePut(key = “#id”, unless=”#result == null”)
@CacheEvict:清空缓存
allEntries,该参数指示是否需要在整个缓存范围内逐出而不仅仅是基于Key的逐条逐出
beforeInvocation,该参数指定逐出缓存是在方法执行前还是方法执行后(默认方法执行后)。在默认情况下,如果方法未执行(可能已经被缓存)或者引发异常,缓存是不会被移除的。而beforeInvocation=true逐出缓存则是在方法调用前发生。适用于移除操作和方法结果没有必要联系的情况。
@Caching:组合定义多种缓存功能
@CacheConfig:用于标注在类上,可以存放该类中所有缓存的公有属性,比如设置缓存空间的名字cacheNames、key生成策略keyGenerator、缓存管理器cacheManager
3.实例
@Service
@CacheConfig(cacheNames = "user",keyGenerator = "keyGenerator")
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService {
@Cacheable(value = "user", key = "'list'")
@Override
public List<UserInfo> userList() {
return userInfoMapper.selectList(new QueryWrapper<>());
}
@Override
@CacheEvict(cacheNames="user", allEntries=true)
public String loadUserList() {
return "逐出user缓存中的所有条目";
}
@Override
@CacheEvict(cacheNames="user", key = "'list'",beforeInvocation = true)
public String loadUserList1() {
return "方法执行前移除缓存";
}
}```