上一篇 :9. Jedis
下一篇 :11. Redis.conf
文章目录
- 1. 概述
- 1.1 SpringData
- 1.2 lettuce
- 2. 部分源码
- 2.1 自动配置
- 2.2 Jedis.pool 不生效
- 3. 使用
- 4. 序列化
- 4.1 为什么要序列化
- 4.2 为什么要自定义序列化
- 4.2 源码
- 4.3 使用
- 5. 工具类
1. 概述
1.1 SpringData
SpringBoot 操作数据都是使用 ——SpringData
以下是 Spring 官网中描述的 SpringData 可以整合的数据源
可以发现 Spring Data Redis
1.2 lettuce
在 SpringBoot 2.X 之后,原来的 Jedis 被替换为了 lettuce
Jedis 和 lettuce 区别
Jedis :采用的是直连的服务,如果有多个线程操作的话是不安全的,就需要使用 Jedis Pool 连接池取解决。问题就会比较多。
lettuce :底层采用 Netty ,实例可以在多个线程中共享,不存在线程不安全的情况。可以减少线程数据了,性能更高。
2. 部分源码
2.1 自动配置
- 找到 spring.factories
spring-boot-autoconfigure-2.3.4.RELEASE.jar → META-INF → spring.factories - 在 spring.factories 中搜索 redis
可以得出配置 Redis,只需要配置 RedisAutoConfiguration 即可
- 点进 RedisAutoConfiguration
- 点进 RedisProperties
- 回到 RedisAutoConfiguration,观察它做了什么
2.2 Jedis.pool 不生效
- 在 RedisAutoConfiguration 类中的 RedisTemplate 方法需要传递一个 RedisConnectionFactory 参数。点进这个参数
- 这是一个结构,查看实现类
- 查看 Jedis 的实现类,下载源码
会发现 ,这个类中很多没有实现的地方。所以 Jedis Pool 不可以 - 查看 Lettuce 的实现类
没有问题
- 这也说明 SpringBoot 更推荐使用 Lettuce
3. 使用
- 新建一个 SpringBoot 项目,勾选上以下
- 相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置连接,application.yml
# 配置 Redis
spring:
redis:
host: 192.168.142.120
port: 6379
- 测试
// 这就是之前 RedisAutoConfiguration 源码中的 Bean
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
/** redisTemplate 操作不同的数据类型,API 和 Redis 中的是一样的
* opsForValue 类似于 Redis 中的 String
* opsForList 类似于 Redis 中的 List
* opsForSet 类似于 Redis 中的 Set
* opsForHash 类似于 Redis 中的 Hash
* opsForZSet 类似于 Redis 中的 ZSet
* opsForGeo 类似于 Redis 中的 Geospatial
* opsForHyperLogLog 类似于 Redis 中的 HyperLogLog
*/
// 除了基本的操作,常用的命令都可以直接通过redisTemplate操作,比如事务……
// 和数据库相关的操作都需要通过连接操作
//RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//connection.flushDb();
redisTemplate.opsForValue().set("key", "呵呵");
System.out.println(redisTemplate.opsForValue().get("key"));
}
4. 序列化
4.1 为什么要序列化
- 新建一个实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
// 实体类序列化在后面加上 implements Serializable
public class User {
private String name;
private String age;
}
- 编写测试类,先不序列化
@Test
public void test() throws JsonProcessingException {
User user = new User("圆","20");
// 使用 JSON 序列化
//String s = new ObjectMapper().writeValueAsString(user);
// 这里直接传入一个对象
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}
- 执行结果
如果序列化就不会报错
- 所以一般实体类都要序列化
4.2 为什么要自定义序列化
执行 3. 使用 中的那个测试类,向数据库中插入了一个中文字符串,虽然在 Java 端可以看到返回了中文,但是在 Redis 中查看是一串乱码。
解决这个问题就需要修改默认的序列化规则。
4.2 源码
- 在 RedisAutoConfiguration 类的 redisTemplate 方法中用到了一个 RedisTemplate 的对象
- 点进 RedisTemplate
- 查看这些序列化对象在哪赋值的
- 但我们需要的是 JSON 序列化,所以就需要自定义一个配置类
4.3 使用
- redisTemplate 模板
@Configuration
public class RedisConfig {
/**
* 编写自定义的 redisTemplate
* 这是一个比较固定的模板
*/
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
// 为了开发方便,直接使用<String, Object>
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
// Json 配置序列化
// 使用 jackson 解析任意的对象
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 使用 objectMapper 进行转义
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 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);
// 把所有的配置 set 进 template
template.afterPropertiesSet();
return template;
}
}
清空一下数据库
再次执行之前那个插入 User 对象的测试类
发现执行成功,没有报错,并且在 Redis 中也没有转义字符了
- 但是去获取这个对象或者中文字符串的时候还是会显示转义字符,怎么解决?
只需要在启动 Redis 客户端的时候加上 –raw 即可
redis-cli --raw -p 6379
5. 工具类
狂神-Redis-工具类