独角兽企业重金招聘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》对你有帮助,请点赞、收藏,并留下你的观点哦!