失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > SpringBoot集成Redis--配置自定义的RedisCacheManager

SpringBoot集成Redis--配置自定义的RedisCacheManager

时间:2021-11-22 08:25:06

相关推荐

SpringBoot集成Redis--配置自定义的RedisCacheManager

独角兽企业重金招聘Python工程师标准>>>

配置自定义的RedisCacheManager--1自定义键生成规则

默认的键生成器

当不指定缓存的key时,SpringBoot会使用SimpleKeyGenerator生成key。

SimpleKeyGenerator

SimpleKey

查看源码可以发现,它是使用方法参数组合生成的一个key。

通过SpEL自定义键生成规则

诸如下面红框的代码,SpEL实际上可以写非常复杂的生成规则。

自定义键生成器

在 @Configuration标注的类中,可以根据自己设计的规则自定义键生成器。

自定义键生成器代码

/*** 新的键生成规则*/@Bean @Override public KeyGenerator keyGenerator() {return new KeyGenerator(){public Object generate(Object target, Method method, Object... params){StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append("::" + method.getName() + ":");for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};}

代码分析

上面自定义的键生成器键的生成规则是:包名+方法名+参数列表。

配置自定义的RedisCacheManager--2创建RedisTemplate模板时自定义序列化器

RedisTemplate默认提供的序列化器

RedisSerializer redis序列化的接口类

OxmSerializer xml到object的序列化/反序列化

StringRedisSerializer string字符串的序列化/反序列化

JacksonJsonRedisSerializer json到object的序列化/反序列化

Jackson2JsonRedisSerializer json到object的序列化/反序列化

JdkSerializationRedisSerializer java对象的序列化/反序列化

RedisTemplate默认使用的是JdkSerializationRedisSerializer

常见序列化方式的特点

JdkSerializationRedisSerializer:JDK自带的序列化方式、存储的字符串内容在序列化的情况下偏长,会占用过多的内存

OxmSerializer:序列化的时间相对较长

Jackson2JsonRedisSerializer:json数据格式、序列化时间和序列化之后内容的长度都要优于前两种

自定义序列化器--使用Jackson2JsonRedisSerializer

代码

/*** RedisTemplate 使用 Jackson2JsonRedisSerializer 作为序列化器* @return*/@Bean public RedisTemplate<String, String> redisTemplate() {StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}

Jackson2JsonRedisSerializer的序列化器需要引入Jackson的依赖

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.6.7</version></dependency>

配置自定义的RedisCacheManager--3示例代码

总体项目结构

POM文件

<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance"xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ding.data</groupId><artifactId>RedisCacheCase</artifactId><version>0.0.1-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><boot.version>1.3.5.RELEASE</boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${boot.version}</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>${boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-redis</artifactId><version>${boot.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.6.7</version></dependency><!-- <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>19.0</version></dependency> --></dependencies></project>

配置文件application.yml

spring:cache:#缓存名称#cache-names: guavaDemo#缓存最大数量500条, 缓存失效时间 6个小时#guava.spec: maximumSize=500,expireAfterWrite=360m# REDIS (RedisProperties) redis :host : localhost # server host port : 6379 # connection port password : 123database : 1pool.max-idle : 8 # pool settings ... pool.min-idle : 1pool.max-active : 8 pool.max-wait : -1

主启动类

package com.ding.data;import java.text.SimpleDateFormat;import java.util.Date;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cache.annotation.EnableCaching;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import com.ding.data.cache.DataCache;/*** 是Spring Boot项目的核心注解,主要是开启自动配置*/@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan@RestController// 开启缓存@EnableCachingpublic class RedisCacheCase {@Autowiredprivate DataCache dataCache;public static void main(String[] args) {SpringApplication.run(RedisCacheCase.class, args);}@RequestMapping("/put")public String put(Long id, String value) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(new Date()) + " : value is " + dataCache.put(id, value) ;}@RequestMapping("/get")public String query(Long id){SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(new Date()) + " : value is " +dataCache.query(id) ;}@RequestMapping("/remove")public String remove(Long id) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");dataCache.remove(id) ;return sdf.format(new Date()) + " : success " ;}}

配置类代码

package com.ding.data.config;import java.lang.reflect.Method;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.interceptor.KeyGenerator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;@Configurationpublic class MyRedisCacheConfig extends CachingConfigurerSupport{@Autowiredprivate JedisConnectionFactory jedisConnectionFactory;@Beanpublic CacheManager cacheManager() {RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate());redisCacheManager.setDefaultExpiration(86400);return redisCacheManager;}/*** RedisTemplate 使用 Jackson2JsonRedisSerializer 作为序列化器* @return*/@Bean public RedisTemplate<String, String> redisTemplate() {StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}/*** 新的键生成规则*/@Bean @Override public KeyGenerator keyGenerator() {return new KeyGenerator(){public Object generate(Object target, Method method, Object... params){StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append("::" + method.getName() + ":");for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};}}

业务层代码

package com.ding.data.cache;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;import javax.annotation.PostConstruct;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.ponent;@Componentpublic class DataCache {private Map<Long, String> dataMap = new HashMap<Long, String>();/*** 初始化*/@PostConstructpublic void init() {dataMap.put(1L, "张三");dataMap.put(2L, "李四");dataMap.put(3L, "王五");}/*** 查询* 如果数据没有缓存,那么从dataMap里面获取,如果缓存了,* 那么从redisDemo里面获取* 并且将缓存的数据存入到 redisDemo里面* 其中key 为 #id+dataMap*/// @Cacheable(value="redisDemo" ,key="#id + 'dataMap'")@Cacheable(value="redisDemo")public String query(Long id) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(new Date()) + " : query id is " + id);return dataMap.get(id);}/*** 插入 或者更新* 插入或更新数据到dataMap中* 并且缓存到 redisDemo中* 如果存在了那么更新缓存中的值* 其中key 为 #id+dataMap*/// @CachePut(value="redisDemo" ,key="#id + 'dataMap'")@CachePut(value="redisDemo")public String put(Long id, String value) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);dataMap.put(id, value);// data persistencereturn value;}/*** 删除* 删除dataMap里面的数据* 并且删除缓存redisDemo中的数据* 其中key 为 #id+dataMap*/// @CacheEvict(value="redisDemo" , key="#id + 'dataMap'")@CacheEvict(value="redisDemo")public void remove(Long id) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");dataMap.remove(id);// data remove }}

测试

依次访问:

http://localhost:8080/get?id=1

http://localhost:8080/get?id=2

http://localhost:8080/put?id=1&value=meixi

http://localhost:8080/put?id=1&value=neimaer

http://localhost:8080/put?id=1&value=cluo

查看Redis内存的内容,如下(因为Redis的database参数用的1,所以用的是Redis中的db1库)

与代码的逻辑是相符的,但是出现了新的问题,除了 @Cacheable注解的方法仍然起到缓存的作用,其他的缓存方法实际上没起作用。这主要是因为现在缓存键生成的规则不具备重复利用性,实际项目需要根据需求对键生成规则进行修改的。

代码改造一下:使@CachePut注解的方法也能起作用

新增一个类MyKeyGenerator

package com.ding.data.config;import java.lang.reflect.Method;import org.springframework.cache.interceptor.KeyGenerator;import org.ponent;@Componentpublic class MyKeyGenerator implements KeyGenerator{public Object generate(Object target, Method method, Object... params) {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append("::" + "query" + ":" + params[0].toString());return sb.toString();}}

DataCache类中@CachePut标注的方法改造如下

/*** 插入 或者更新* 插入或更新数据到dataMap中* 并且缓存到 redisDemo中* 如果存在了那么更新缓存中的值* 其中key 为 #id+dataMap*/// @CachePut(value="redisDemo" ,key="#id + 'dataMap'")@CachePut(value="redisDemo",keyGenerator="myKeyGenerator")public String put(Long id, String value) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);dataMap.put(id, value);// data persistencereturn value;}

keyGenerator="myKeyGenerator"啥意思

意思就是说明这个方法的键生成规则采用myKeyGenerator这个类

再次测试(先将刚才测试的数据都清空)

依次访问:

http://localhost:8080/get?id=1

http://localhost:8080/put?id=1&value=meixi

查看Redis数据库中的数据

可见改造后@CachePut标注的方法也起作用了。

但是现在代码仍然太“死性”,无法应用于实际项目。要想应用于实际项目,还需要根据具体需求进行设计。

如果觉得《SpringBoot集成Redis--配置自定义的RedisCacheManager》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。