https://blog.csdn.net/qq_33999844/article/details/82182427
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
具體解釋請關注: