【1】pom依赖
添加redis依赖如下:
<!--整合redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <!-- 1.5的版本默认采用的连接池技术是jedis 2.0以上版本默认连接池是lettuce, 在这里采用jedis,所以需要排除lettuce的jar --> <exclusions> <exclusion> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </exclusion> <exclusion> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </exclusion> </exclusions> </dependency> <!-- 添加jedis客户端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <!--spring2.0集成redis所需common-pool2 必须加上,jedis依赖此 --> <!-- spring boot 2.0 的操作手册有标注 地址是:https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.5.0</version> <!--<version>2.4.2</version>--> </dependency>
【2】yml配置
yml中对redis配置如下:
spring: redis: host: 127.0.0.1 port: 6379 password: admin jedis: pool: #最大连接数 max-active: 1024 #最大阻塞等待时间(负数表示没限制) max-wait: 20000 #最大空闲 max-idle: 200 #最小空闲 min-idle: 10 #连接超时时间 timeout: 10000
注意,与SpringBoot1.X整合Redis配置不同。
【3】Redis配置类
MyRedisConfig如下:
@Configuration// 必须加,使配置生效 @EnableCaching //开启缓存 <cache/> 可不加 public class MyRedisConfig extends CachingConfigurerSupport { private static final Logger log = LoggerFactory.getLogger(MyRedisConfig.class); @Autowired private JedisConnectionFactory jedisConnectionFactory; //自定义缓存控制器 @Bean @Override public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题),过期时间600秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } @Bean public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory ) { //设置序列化 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置redisTemplate RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(jedisConnectionFactory); RedisSerializer stringSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringSerializer); // key序列化 redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // value序列化 redisTemplate.setHashKeySerializer(stringSerializer); // Hash key序列化 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); // Hash value序列化 redisTemplate.afterPropertiesSet(); return redisTemplate; } //重写异常处理器 @Override @Bean public CacheErrorHandler errorHandler() { // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 log.info("初始化 -> [{}]", "Redis CacheErrorHandler"); CacheErrorHandler cacheErrorHandler = 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); } }; return cacheErrorHandler; } }
其实这里主要是注入了自定义的redisTemplate,替换了默认的jdk 序列化机制,使存入redis中的value json化,体验更友好。
【4】测试实例
测试value为String和Object的存取。
@Autowired StringRedisTemplate stringRedisTemplate; @Autowired RedisTemplate redisTemplate; @Test public void testRedis(){ // 测试redis if(stringRedisTemplate.hasKey("hello")){ String hello = stringRedisTemplate.opsForValue().get("hello"); System.out.println("从redis中获取 key-hello--value : "+hello); stringRedisTemplate.opsForValue().set("jane","is a boy"); } SysApk sysApk = sysApkMapper.selectByPrimaryKey(1L); redisTemplate.opsForValue().set("sysApk",sysApk); SysApk sysApk2 = (SysApk) redisTemplate.opsForValue().get("sysApk"); System.out.println(sysApk2); }
【Tips】
需要注意的是Redis中value是不允许为null或者尽量不要为null的。使用Jedis客户端直接set键值的时候,如果value为null,会抛异常:
在SpringBoot下使用StringRedisTemplate或者RedisTemplate进行键值set时,如果value为null,会将其序列化为,存入redis不会抛出异常。
redisTemplate.opsForValue().set("sysApk",null); System.out.println(redisTemplate.opsForValue().get("sysApk")); //打印结果 :null // 客户端直接获取 127.0.0.1:6379> get sysApk ""
不过还是建议redis中value值一般不要为null。
前面我们使用的是jedis,下面我们使用lettuce。
【5】SpringBoot整合lettuce单节点
① 配置文件
pom文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
配置文件:
@Configuration public class RedisConfig extends CachingConfigurerSupport { @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){ //为了方便,泛型规定为String,Object类型 RedisTemplate<String,Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); //序列化 json解析任意对象 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); //使用ObjectMapper转义 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //String的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); //key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); //hash的key也采用String 的序列化方式 template.setHashKeySerializer(stringRedisSerializer); //value采用jackson的序列化方式 template.setValueSerializer(jackson2JsonRedisSerializer); //hash的value也采用jackson的序列化方式 template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
这样就可以使用redisTemplate进行操作了。
【6】SpringBoot整合lettuce集群
① application配置文件
【5】中是单节点,如果Redis是集群(cluster)形式呢?这里给出参考的配置文件:
#集群配置 spring.redis.cluster.nodes=127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005 spring.redis.lettuce.cluster.refresh.period=20s spring.redis.lettuce.cluster.refresh.adaptive=true #Redis数据库索引(默认为0) spring.redis.database=0 spring.redis.password=123456 #连接超时时间(毫秒) spring.redis.timeout=5000 #lettuce连接池最大连接数(使用负值表示没有限制) spring.redis.lettuce.pool.max-active=8 #最大阻塞等待时间(负数表示没限制) spring.redis.lettuce.pool.max-wait=-1 #连接池中的最大空闲连接 spring.redis.lettuce.pool.max-idle=5 #连接池中的最小空闲连接 spring.redis.lettuce.pool.min-idle=0
配置类同【5】。
② 自定义RedisClusterConfiguration
非必要哦。
@Value("${redis.server.nodes}") private String redisServerNodes; @Value("${redis.server.password}") private String redisServerPassword; @Bean public RedisClusterConfiguration getRedisClusterConfiguration() { RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(); String[] serverArray = redisServerNodes.split(","); Set<RedisNode> nodes = new HashSet<RedisNode>(); for (String ipPort : serverArray) { String[] ipAndPort = ipPort.split(":"); nodes.add(new RedisNode(ipAndPort[0].trim(), Integer.parseInt(ipAndPort[1]))); } redisClusterConfiguration.setClusterNodes(nodes); RedisPassword pwd = RedisPassword.of(redisServerPassword); redisClusterConfiguration.setPassword(pwd); return redisClusterConfiguration;