content: 
  package com.platform.config;
  
  import cn.hutool.core.lang.Assert;
  import com.alibaba.fastjson.JSON;
  import com.alibaba.fastjson.parser.ParserConfig;
  import com.alibaba.fastjson.serializer.SerializerFeature;
  import lombok.extern.slf4j.Slf4j;
  import org.apache.commons.codec.digest.DigestUtils;
  import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
  import org.springframework.boot.context.properties.EnableConfigurationProperties;
  import org.springframework.cache.Cache;
  import org.springframework.cache.annotation.CachingConfigurerSupport;
  import org.springframework.cache.annotation.EnableCaching;
  import org.springframework.cache.interceptor.CacheErrorHandler;
  import org.springframework.cache.interceptor.KeyGenerator;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.data.redis.cache.RedisCacheConfiguration;
  import org.springframework.data.redis.connection.RedisConnectionFactory;
  import org.springframework.data.redis.core.RedisOperations;
  import org.springframework.data.redis.core.RedisTemplate;
  import org.springframework.data.redis.serializer.RedisSerializationContext;
  import org.springframework.data.redis.serializer.RedisSerializer;
  import reactor.util.annotation.Nullable;
  import java.nio.charset.Charset;
  import java.nio.charset.StandardCharsets;
  import java.time.Duration;
  import java.util.HashMap;
  import java.util.Map;
  
  
  /**
   * @author AllDataDC
   * @date 2023-01-27
   */
  @Slf4j
  @Configuration
  @EnableCaching
  @ConditionalOnClass(RedisOperations.class)
  @EnableConfigurationProperties(RedisProperties.class)
  public class RedisConfig extends CachingConfigurerSupport {
  
      /**
       *  设置 redis 数据默认过期时间，默认2小时
       *  设置@cacheable 序列化方式
       */
      @Bean
      public RedisCacheConfiguration redisCacheConfiguration(){
          FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
          RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
          configuration = configuration.serializeValuesWith(RedisSerializationContext.
                  SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
          return configuration;
      }
  
      @SuppressWarnings("all")
      @Bean(name="myRedisTemplate")
      public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
          RedisTemplate<Object, Object> template = new RedisTemplate<>();
          //序列化
          FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
          // value值的序列化采用fastJsonRedisSerializer
          template.setValueSerializer(fastJsonRedisSerializer);
          template.setHashValueSerializer(fastJsonRedisSerializer);
          // fastjson 升级到 1.2.83 后需要指定序列化白名单
          ParserConfig.getGlobalInstance().addAccept("com.platform.domain");
          ParserConfig.getGlobalInstance().addAccept("com.platform.service.dto");
          // 模块内的实体类
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.mnt.domain");
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.quartz.domain");
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.system.domain");
          // 模块内的 Dto
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.mnt.service.dto");
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.quartz.service.dto");
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.security.service.dto");
          ParserConfig.getGlobalInstance().addAccept("com.platform.modules.system.service.dto");
          // key的序列化采用StringRedisSerializer
          template.setKeySerializer(new StringRedisSerializer());
          template.setHashKeySerializer(new StringRedisSerializer());
          template.setConnectionFactory(redisConnectionFactory);
          return template;
      }
  
      /**
       * 自定义缓存key生成策略，默认将使用该策略
       */
      @Bean
      @Override
      public KeyGenerator keyGenerator() {
          return (target, method, params) -> {
              Map<String,Object> container = new HashMap<>(8);
              Class<?> targetClassClass = target.getClass();
              // 类地址
              container.put("class",targetClassClass.toGenericString());
              // 方法名称
              container.put("methodName",method.getName());
              // 包名称
              container.put("package",targetClassClass.getPackage());
              // 参数列表
              for (int i = 0; i < params.length; i++) {
                  container.put(String.valueOf(i),params[i]);
              }
              // 转为JSON字符串
              String jsonString = JSON.toJSONString(container);
              // 做SHA256 Hash计算，得到一个SHA256摘要作为Key
              return DigestUtils.sha256Hex(jsonString);
          };
      }
  
      @Bean
      @Override
      public CacheErrorHandler errorHandler() {
          // 异常处理，当Redis发生异常时，打印日志，但是程序正常走
          log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
          return new CacheErrorHandler() {
              @Override
              public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                  log.error("Redis occur handleCacheGetError：key -> [{}]", key, e);
              }
  
              @Override
              public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                  log.error("Redis occur handleCachePutError：key -> [{}]；value -> [{}]", key, value, e);
              }
  
              @Override
              public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
                  log.error("Redis occur handleCacheEvictError：key -> [{}]", key, e);
              }
  
              @Override
              public void handleCacheClearError(RuntimeException e, Cache cache) {
                  log.error("Redis occur handleCacheClearError：", e);
              }
          };
      }
  
  }
  
  /**
   * Value 序列化
   *
   * @author AllDataDC
   * @param <T>
   */
   class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
  
      private final Class<T> clazz;
  
      FastJsonRedisSerializer(Class<T> clazz) {
          super();
          this.clazz = clazz;
      }
  
      @Override
      public byte[] serialize(T t) {
          if (t == null) {
              return new byte[0];
          }
          return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
      }
  
      @Override
      public T deserialize(byte[] bytes) {
          if (bytes == null || bytes.length <= 0) {
              return null;
          }
          String str = new String(bytes, StandardCharsets.UTF_8);
          return JSON.parseObject(str, clazz);
      }
  
  }
  
  /**
   * 重写序列化器
   *
   * @author AllDataDC
   */
  class StringRedisSerializer implements RedisSerializer<Object> {
  
      private final Charset charset;
  
      StringRedisSerializer() {
          this(StandardCharsets.UTF_8);
      }
  
      private StringRedisSerializer(Charset charset) {
          Assert.notNull(charset, "Charset must not be null!");
          this.charset = charset;
      }
  
      @Override
      public String deserialize(byte[] bytes) {
          return (bytes == null ? null : new String(bytes, charset));
      }
  
  	@Override
  	public @Nullable byte[] serialize(Object object) {
  		String string = JSON.toJSONString(object);
  
  		if (org.apache.commons.lang3.StringUtils.isBlank(string)) {
  			return null;
  		}
  		string = string.replace("\"", "");
  		return string.getBytes(charset);
  	}
  }
  