SpringBoot 整合 Redis
SpringBoot操作数据:spring-data jpa jdbc mongodb redis !
SpringData也是和SpringBoot齐名的项目!
说明:在SpringBoot2.X之后,原来使用的jedis被替换成了lettuce
jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis pool连接池!更像BIO模式
lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数据了,更像NIO模式
- 提供了对不同 Redis 客户端的整合 (Lettuce和Jedis)
- 提供了 RedisTemplate 统一 API 来操作 Redis
- 支持 Redis 的发布订阅模型
- 支持 Redis 哨兵和 Redis 集群
- 支持基于 Lettuce 的响应式编程
- 支持基于 JDK、JSON、字符串、Spring 对象的数据序列化及反序列化
- 支持基于 Redis 的 JDKCollection 实现
SpringDataRedis 中提供了 RedisTemplate 工具类,其中封装了各种对 Redis 的操作。并且将不同数据类型的 API 封装到了不同的类型中:
API | 返回值类型 | 说明 |
---|---|---|
redisTemplate.opsForValue() | ValueOperations | 操作 String 类型数据 |
redisTemplate.opsForHash() | HashOperations | 操作 Hash 类型数据 |
redisTemplate.opsForList() | ListOperations | 操作 List 类型数据 |
redisTemplate.opsForSet() | SetOperations | 操作 Set 类型数据 |
redisTemplate.opsForZSet() | ZSetOperations | 操作 SortedSet 类型数据 |
整合测试
1、导入依赖
<dependencies>
<!--Redis 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--连接池依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
</dependencies>
2、配置连接
spring:
redis:
host: 127.0.0.1
port: 6379
database: 0
password: 123456
# 连接超时时间
timeout: 1800000
lettuce:
pool:
# 连接池最大连接数
max-active: 20
# 最大阻塞等待时间(负数表示没有限制)
max-wait: 1
# 连接池中最大空闲连接
max-idle: 5
# 连接池中最小空闲连接
min-idle: 0
3、测试
@SpringBootTest
class SpringbootRedisApplicationTests {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
void contextLoads() {
//redisTemplate 操作不同的数据类型
//opsForValue //操作字符串 类似String
//opsForList //操作List 类似List
//opsForSet //opsForHash //opsForZSet //opsForGeo
//除了基本的操作,我们常用的方法都可以直接通过redisTemplate操作,比如事务,和基本的CRUD
redisTemplate.opsForValue().set("myKey","myValue");
System.out.println(redisTemplate.opsForValue().get("myKey"));
}
}
源码分析:
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")//我们可以自定义一个redisTemplate来替换这个默认的!
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {
//默认的RedisTemplate 没有过多的设置,redis对象都是需要序列化的!
//两个泛型都是Object类型,Object的类型,我们使用需要强制转换<String,Object>
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean//由于String 是redis中最常用的类型,所以单独出来一个bean!
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
RedisTemplate 可以接收任意 Object 作为值写入 Redis,只不过写入前会把 Object 序列化位字节字节形式,默认是采用 JDK 序列化
缺点
- 可读性差
- 占用内存大
配置 redisTemplate 序列化方式
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 创建 RedisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// key 和 hashKey 采用 string 序列化
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
// value 和 hashValue 采用 JSON 序列化
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
return redisTemplate;
}
}
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void test() {
Student student = new Student(1, "HuDu", 18);
redisTemplate.opsForValue().set("student", student);
System.out.println(redisTemplate.opsForValue().get("student"));
}
}
存入 Redis 之后,结果为
127.0.0.1:6379> get student
"{\"@class\":\"com.hudu.domain.entry.Student\",\"id\":1,\"name\":\"HuDu\",\"age\":18}"
尽管 JSON 的序列化方式可以满足我们的需求,但依然存在一些问题,为了在反序列化时,知道对象的类型,JSON 序列化器会将类的 class 类型写入 json 结果中,存入 redis,会带来额外的内存开销。
为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用 String 序列化器 ,要求只能存储 String 类型的 key 和 value。当需要存储 Java 对象时,手动完成对象的序列化和反序列化。
官方提供了StringRedisTemplate
,通过手动将对象转化为 json 字符串存入 redis 中。
本作品采用《CC 协议》,转载必须注明作者和本文链接