本文有部分代碼是抄襲的。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)
搜了半天沒解決方案。