集成 Spring data redis 筆記

本文有部分代碼是抄襲的。java

1 :引入依賴

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>
  <version>${spring-data-redis.version}</version>
</dependency>
<!-- spring-data-redis 1.8須要commons-pool2,若是要用到鏈接池的話  -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>${commons-pool2.version}</version>
</dependency>

<!-- spring-data-redis實現了lettuceFactory,可是1.8針對的是lettuce 4.X的實現,所以不能使用高版本 -->
<dependency>
  <groupId>biz.paluch.redis</groupId>
  <artifactId>lettuce</artifactId>
  <version>${lettuce.version}</version>
</dependency>

/**
 * 配置緩存
 */

@EnableCaching
public class CachingConfig extends CachingConfigurerSupport {git

@Resource(name = "redisTemplate")
private RedisTemplate<Object, Object> redisTemplate;

@Override
@Bean(name = "redisCache")
public CacheManager cacheManager() {

    ///須要更快啓動cacheManager就開啓這個
    // manager.afterPropertiesSet();
    // ConcurrentMapCacheManager manager=new ConcurrentMapCacheManager();
    RedisCacheManager manager = new RedisCacheManager(redisTemplate);
    return manager;
}

@Override
@Bean(name = "redisKeyGen")
public KeyGenerator keyGenerator() {
    return new KeyGenerator() {
        @Override
        public Object generate(Object target, Method method, Object... objects) {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : objects) {
                sb.append(obj.toString());
            }
            return sb.toString();
        }
    };
}

}github


配置redisredis

public class RedisConfig {spring

private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class);


private String host = "localhost";

private int port = 6379;

private String password = "redis";

private int database = 0;


/**
 * 使用這個鏈接池,須要commons-pool2依賴
 * lettuce其實沒有必要使用鏈接池 https://github.com/lettuce-io/lettuce-core/wiki/Connection-Pooling
 *
 * @return
 */
@Bean(value = "lettucePool")
public LettucePool lettucePool() {
    DefaultLettucePool pool = new DefaultLettucePool();
    pool.setDatabase(0);
    pool.setHostName("localhost");
    pool.setPort(6379);
    //調用這個方法,確保鏈接池被初始化
    pool.afterPropertiesSet();
    return pool;
}


/**
 * 設置 redis鏈接工廠,經過鏈接池的方式來初始化工廠
 *
 * @return
 */
//@Lazy(value = false)
@Bean(name = "redisConnectionFactory")
@DependsOn(value = "lettucePool")
public RedisConnectionFactory redisConnectionFactory() {
    //Linux使用這種方式初始化工廠
    //return new LettuceConnectionFactory(new RedisSocketConfiguration("/var/run/redis.sock"));
    LettuceConnectionFactory factory = new LettuceConnectionFactory(lettucePool());
    //若是不使用鏈接池初始化工廠,則須要調用這個方法
    //factory.afterPropertiesSet();
    return factory;
}


/**
 * 設置redis操做模板
 *
 * @param redisConnectionFactory
 * @return
 */
@Bean(name = "redisTemplate")
@DependsOn(value = "redisConnectionFactory")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory,
                                                   Jackson2JsonRedisSerializer<Response> jackson2JsonRedisSerializer,
                                                   StringRedisSerializer stringRedisSerializer) {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);

    //設置序列化方式
    
    template.setHashKeySerializer(jackson2JsonRedisSerializer);
    template.setHashValueSerializer(jackson2JsonRedisSerializer);
    template.setKeySerializer(jackson2JsonRedisSerializer);
    template.setValueSerializer(jackson2JsonRedisSerializer);
    
    template.setStringSerializer(stringRedisSerializer);

    return template;
}

}apache


設置序列化json

public class SerializerConfig {segmentfault

/**
 * 配置 jackson mapper
 * @return
 */
@Lazy(value = false)
@Bean(name = "jacksonMapper")
public ObjectMapper jacksonMapper(){
    ObjectMapper mapper=new ObjectMapper();
    //只針對非空的值進行序列化
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

    // 去掉各類@JsonSerialize註解的解析
    //mapper.configure(MapperFeature.USE_ANNOTATIONS, false);

    // 將類型序列化到屬性json字符串中 有的文章說須要這個才能正確反序列化
    //mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

    // 對於找不到匹配屬性的時候忽略報錯
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    // 不包含任何屬性的bean也不報錯
    mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    return mapper;
}


/**
 * 關鍵
 * Jackson2JsonRedisSerializer 是泛型,須要指定類型
 * 這樣才能正確反序列化,否則會拋出 java.util.LinkedHashMap cannot be cast YOUR OBJECT 異常
 * @return
 */
@Lazy(value = false)
@Bean(name = "jackson2JsonRedisSerializer")
public Jackson2JsonRedisSerializer<Response> jackson2JsonRedisSerializer(){
    Jackson2JsonRedisSerializer<Response> jsonRedisSerializer=new Jackson2JsonRedisSerializer<>(Response.class);
    jsonRedisSerializer.setObjectMapper(jacksonMapper());
    return jsonRedisSerializer;
}


@Lazy(value =false)
@Bean (name = "stringRedisSerializer")
public StringRedisSerializer stringRedisSerializer(){
    return new StringRedisSerializer(StandardCharsets.UTF_8);
}

}緩存


最後在須要的地方開啓註解緩存便可
@CacheConfig(cacheManager = "redisCache",cacheNames = {"bxe"})
@Cacheableapp


弄這個破玩意好幾天,尤爲是spring data redis還挑lettuce的版本,我把git的源碼下載一遍本身編譯都報錯,最後才發現是版本問題。
第二個坑:RedisSerializer須要指定對象的數據類型,否則反序列化報錯。
第三: segmentfault的編輯器很是很差用。

--------update
上面的配置有個缺陷,就是隻能指定數據類型去緩存到redis。

其實還能夠配置一個GenericJackson2JsonRedisSerializer

@Bean(name = "jsonRedisSerializer")
public GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer(){
    GenericJackson2JsonRedisSerializer jsonRedisSerializer=new GenericJackson2JsonRedisSerializer(「@class);
    return jsonRedisSerializer;
}

但我持久層是 Spring data JPA。
查詢分頁結果時,會沒法反序列化。
Could not read JSON: Cannot construct instance of `org.springframework.data.domain.PageImpl` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

搜了半天沒解決方案。

相關文章
相關標籤/搜索