11. 集成 Redis
11.1 说明
-
SpringBoot 操作数据:sping-data、jpa、jdbc、mongodb、redis
-
SpringBoot 2.× 后,jedis 被替换为 lettuce
jedis:采用直连,多线程操作不安全,增强安全性需使用 jedis pool 连接池!更像 BIO 模式。
lettuce:采用 netty,实例可在多个线程中共享,不存在线程不安全的情况!更像 NIO 模式。
11.2 源码分析
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 默认的 RedisTemplate 没有过多的设置,redis 对象都需要序列化
// 两个泛型都是 Object,需要强制转换为 <String, Object>
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
// 由于 String 是常用类型所以单独提出一个 bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
11.3 测试
(1) 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2) 配置 redis
# application.properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
(3) 测试
● 传输字符串
@SpringBootTest
class RedisApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
/**
* redisTemplate 可操作不同的数据类型,可完成基本的操作,如 CRUD
* opsForValue 字符串
* opsForList
* opsForSet
* opsForHash
* opsForZSet
* opsForGeo
* opsForHyperLogLog
*
* 获取 redis 连接对象
* RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
* connection.flushDb();
* connection.flushAll() ;
*/
redisTemplate.opsForValue().set("myKey", "why");
System.out.println("myKey: " + redisTemplate.opsForValue().get("myKey"));
}
}
● 传输对象
// 实体类
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String password;
}
@Test
void test() throws JsonProcessingException {
User user = new User("why", "123");
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
● 传输 JSON
@Test
void test() throws JsonProcessingException {
User user = new User("why", "123");
// 将 Object 转换为 Json
String jsonUser = new ObjectMapper().writeValueAsString(user);
redisTemplate.opsForValue().set("user", jsonUser);
System.out.println(redisTemplate.opsForValue().get("user"));
}
● 传输序列化对象
// 序列化的实体类
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String name;
private String password;
}
@Test
void test() throws JsonProcessingException {
User user = new User("why", "123");
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
● Redis 用户端乱码问题
(4) 自定义配置类
@Configuration
public class RedisConfig {
// 自定义 redisTemplate, 修改 RedisAutoConfiguration 中的 Bean
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
// <String, Object> 类型便于开发
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// Json 序列化配置
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);
// 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;
}
}
@Test
void test() throws JsonProcessingException {
User user = new User("why", "123");
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}