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 {@Autowiredprivate RedisTemplate redisTemplate;@Testvoid 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 转换为 JsonString 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"));
}