# redis缓存管理配置
#设置缓存类型位redis
spring.cache.type=redis
#配置缓存名称
spring.cache.cache-names=redisCache
#是否允许redis缓存空值
spring.cache.redis.cache-null-values=true
#redis的键前缀
spring.cache.redis.key.prefix=
#缓存超时时间戳,配置为0则不设置超时时间
spring.cache.redis.time-to-live=0ms
#是否启用redis的键前缀
spring.cache.redis.use-key-preficx=true
在SpringBoot中一般使用RedisTemplate提供的方法来操作Redis,Springboot会默认配置redistemplate。(这句话我写来干嘛?)
@Configuration
//Redis 缓存配置类
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public CacheManager cacheManager(RedisTemplate,?> redisTemplate) {
RedisSerializer stringSerializer = new StringRedisSerializer();
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值//(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括//private和public
om.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.PUBLIC_ONLY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比//如String,Integer等会抛出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
}
上述代码主要是使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值,因为默认使用JDK的序列化方式,JDK的序列化方式,数据在redisclient(可使用redisclient这一工具来操控redis)上不能正常显示。
注:
1,用StringRedisSerializer进行序列化的值,在Java和Redis中保存的内容是一样的
2,用Jackson2JsonRedisSerializer进行序列化的值,在Redis中保存的内容,比Java中多了一对双引号。
3,用JdkSerializationRedisSerializer进行序列化的值,对于Key-Value的Value来说,是在Redis中是不可读的。对于Hash的Value来说,比Java的内容多了一些字符。
有些demo在用java(jredis)操控redis时,会使用jredis将数据(对象)存储到redis中,此时可以使用jdk序列化方式将对象存储到redis中,也可以将对象转为json存储到redis中,具体代码不再列出,懂的都懂。
还需要在service层加入几个注解,这几个注解在中文社区上解释的并不完整(大家都在CV)
具体可去查看spring官方文档(reference doc或api均可)
使用Redisclient查看数据如下:
代码如下:
@CacheConfig(cacheNames="categories")
public class CategoryService {
@Autowired CategoryDAO categoryDAO;
@CacheEvict(allEntries=true)
// @CachePut(key="'category-one-'+ #p0")
public void add(Category bean) {
categoryDAO.save(bean);
}
@CacheEvict(allEntries=true)
// @CacheEvict(key="'category-one-'+ #p0")
public void delete(int id) {
categoryDAO.delete(id);
}
@Cacheable(key="'categories-one-'+ #p0")//这里对应着categories-one-84
//其中#p0的意思是指加有@Cacheable注解的方法中的第一个参数
public Category get(int id) {
Category c= categoryDAO.findOne(id);
return c;
}
@Cacheable(key="'categories-page-'+#p0+ '-' + #p1")
//这里对应着categories-page-0-5,而categories-all是随着categories-page-0-5一起加//入redis数据库中的
public Page4Navigator list(int start, int size, int navigatePages) {
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = new PageRequest(start, size,sort);
Page pageFromJPA =categoryDAO.findAll(pageable);
return new Page4Navigator<>(pageFromJPA,navigatePages);
}
这里的categories~keys就是利用了@CacheConfig(cacheNames="categories")的categories做前缀,这个sorted set中存有这四个数据。
而这四个数据的名称(即key)是由@Cacheable(key="'categories-one-'+ #p0")等等决定的。
@CacheEvict(allEntries=true)可以将redis上相同cacheNames的数据清除掉(即categories~keys上的数据)。
@Cacheable
注释可让您指定如何通过其key
属性生成密钥。您可以使用SpEL选择感兴趣的参数(或其嵌套属性),执行操作,甚至调用任意方法,而无需编写任何代码或实现任何接口。
以下示例使用各种SpEL声明(如果您不熟悉SpEL,请帮忙并阅读Spring Expression Language):
@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@CacheEvict
需要指定一个或多个受操作影响的缓存,允许指定自定义缓存和键解析或条件,并具有一个额外的参数(allEntries
),该参数指示是否需要在整个缓存范围内逐出执行
@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)
当需要清除整个缓存区域时,此选项非常有用。如前面的示例所示,而不是逐出每个条目(这会花费很长时间,因为它效率低下),而是通过一次操作删除所有条目。