1.redis是内存数据库,可以单独作为数据库(有持久化方案),也可以作为缓存(一般为MySQL搭配)
1.1 可以通过jedis,代码的方式手动将其传入redis作为缓存;
1.2 也可以通过注解的方式,和spring boot整合,通过@cacheable...的方式自动存入redis(本文的探讨方式)
2.springboot2.x与1.x版本用法相差较大
例如:缓存管理器的自定义方式
@Bean //spring boot1.x版本的使用方式
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager= new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(60);
Map<String,Long> expiresMap=new HashMap<>();
expiresMap.put("Product",5L);
cacheManager.setExpires(expiresMap);
return cacheManager;
}
到了2.x版本,没有这个构造方法,该方式已经不能使用;
3.springboot2.x使用redis作为缓存
思路:
1.编写RedisConfig配置类----配置类里面重构cacheManager和redisTemplate; 后期可以在该类中设置key的生成策略等...
2.实现对象的缓存,定义自己的序列化和反序列化器。(必须定义自己的)
在redisConfig类中不要导入:
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;//不要导入
导入:
import zmc.leon.mcd.Util.FastJsonRedisSerializer;//自定义的序列化反序列化器
3.spring boot+mybatis的controller、service、dao层的编写(省略)
RedisConfig.java
package zmc.leon.mcd.Config;
//import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.alibaba.fastjson.parser.ParserConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
import zmc.leon.mcd.Util.FastJsonRedisSerializer;
import javax.crypto.KeyGenerator;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
/**
* 重写Redis序列化方式,使用Json方式:
* 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
* Spring Data JPA为我们提供了下面的Serializer:
* GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
* 在此我们将自己配置RedisTemplate并定义Serializer。
*
*/
// 存入redis时,默认使用的是JdkSerializationRedisSerializer,使得存入的数据全部序列化了,所需自定义一个RedisTemplate,使用其他序列化方式
//当redis依赖包导入的时候,默认的cache即可自动变成redis模式;如果只是导入cache的依赖,则默认的是simpleCacheManager;
// 使用redis缓存时,RedisCacheManager生成RedisCache后生成缓存时默认使用JdkSerializationRedisSerializer序列化(cache存储的时候)
//当ioc容器内没有自定义的缓存管理器的时候---默认使用自带的;
//当通过@Bean在ioc容器中注入了以下管理器,则会使用自定义的管理器;
// @Bean
// public CacheManager cacheManager(RedisConnectionFactory factory) {
// RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
// config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置
// .disableCachingNullValues(); // 不缓存空值
//
// // 设置一个初始化的缓存空间set集合
// Set<String> cacheNames = new HashSet<>();
// cacheNames.add("my-redis-cache1");
// cacheNames.add("my-redis-cache2");
//
// // 对每个缓存空间应用不同的配置
// Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
// configMap.put("my-redis-cache1", config);
// configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));
//
// RedisCacheManager cacheManager = RedisCacheManager.builder(factory) // 使用自定义的缓存配置初始化一个cacheManager
// .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
// .withInitialCacheConfigurations(configMap)
// .build();
// return cacheManager;
// }
@Bean
@Primary//当有多个管理器的时候,必须使用该注解在一个管理器上注释:表示该管理器为默认的管理器
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//初始化一个RedisCacheWriter
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
//序列化方式1
//设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下(4行)注释代码为默认实现
// ClassLoader loader = this.getClass().getClassLoader();
// JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader);
// RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer);
// RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
//序列化方式1---另一种实现方式
//RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();//该语句相当于序列化方式1
//序列化方式2
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);//JSONObject
RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer);
RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
//序列化方式3
//Jackson2JsonRedisSerializer serializer=new Jackson2JsonRedisSerializer(Object.class);
//RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
//RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(100));//设置过期时间
// //设置默认超过期时间是30秒
// defaultCacheConfig.entryTtl(Duration.ofSeconds(30));
//初始化RedisCacheManager
RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
//设置白名单---非常重要********
/*
使用fastjson的时候:序列化时将class信息写入,反解析的时候,
fastjson默认情况下会开启autoType的检查,相当于一个白名单检查,
如果序列化信息中的类路径不在autoType中,
反解析就会报com.alibaba.fastjson.JSONException: autoType is not support的异常
可参考 https://blog.csdn.net/u012240455/article/details/80538540
*/
ParserConfig.getGlobalInstance().addAccept("zmc.leon.mcd.entity.");
return cacheManager;
}
/**
* 设置 redis 数据默认过期时间
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(30));
return configuration;
}
@Bean(name = "redisTemplate")
@SuppressWarnings("unchecked")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//使用fastjson序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
// @Bean
// 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();
// }
// };
// }
}
FastJsonRediaSerializer.java
package zmc.leon.mcd.Util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
/*
要实现对象的缓存,定义自己的序列化和反序列化器。使用阿里的fastjson来实现的比较多。
*/
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (null == t) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (null == bytes || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
注意:
1.一定要导入自己的util包
import zmc.leon.mcd.Util.FastJsonRedisSerializer;
2.缓存管理器中一定要加入(白名单),其中的包名:为自己的bean类的所在包
ParserConfig.getGlobalInstance().addAccept("zmc.leon.mcd.entity.");
没有的话会有以下异常:
com.alibaba.fastjson.JSONException: autoType is not support
具体解释请关注:
https://blog.csdn.net/u012240455/article/details/80538540