【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>
配置文件:
#Redis服务器地址(单机redis配置方式)
spring.redis.host=127.0.0.1
#Redis服务器连接端口(单机redis配置方式)
spring.redis.port=7000
#Redis密码
spring.redis.password=123456
② 配置类
@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;
参考博客:
Spring缓存默认配置与运行流程;
缓存入门与注解使用示例;
SpringBoot1.5使用Redis详解;
Redis安装与详解系列。