开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
SpringBoot整合Redis
SpringBoot操作数据:spring-data jpa jdbc mongodb redis
SpringData是和SpringBoot齐名的项目
如果是SpringBoot2.0以上配置集群的话一定要使用lettuce.pool下面的属性
在SpringBoot2.x之后 jedis被替换成了lettuce
jedis和lettuce有什么区别呢?
jedis:
用作于2.0之前,底层采用的是直连的serve,多个线程操作的话是不安全的,如果想要避免这种情况,需要使用jedis的连接池来解决 更像BIO(阻塞)模式(dubbo)
lettuce:
底层采用netty(高性能的网络框架,异步请求),实例key在线程中进行共享,不存在线程不安全的情况,可以减少线程数据,性能更加的高 更像NIO模式
源码分析:
//原文:如果不存在bean才生效 也就是告诉我们可以自己定义一个RedisTemplate来替换这个默认的
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//默认的RedisTemplate 没有过多的设置,redis对象的保存都是需要序列化的,尤其是使用netty NIO这种异步的
//两个泛型都是object类型,后面使用需要强制转换,我们期望的数据类型应该是<string,object>
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
//由于string类型是redis最长使用的数据类型,所以单独提出来了一个方法(bean)
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
综上所述,我们整合测试一下
1.导入依赖(pom)
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置连接(application.properties(yml))
# SpringBoot所有的配置类,都有一个自动配置类 RedisAutoConfiguration
# 自动配置类都会绑定一个properties配置文件 RedisProperties
#配置redis的ip 如果是本机的话可以写localhost或者127.0.0.1 如果是远程的话就写远程的ip即可
spring.redis.host=localhost
#配置redis的端口号 默认都是6379
spring.redis.port=6379
#配置redis使用的数据库 注:redis共有16个数据库 默认使用第0个
spring.redis.database=2
#配置redis的集群 ( 如果是SpringBoot2.0以上配置集群的话一定要使用lettuce.pool下面的属性 )
spring.redis.lettuce.pool
3.测试
package com.wyh;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
class SpringBootRedis01ApplicationTests {
//注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
//很多数据类型api命令是以OpsFor开头的,操作不同的数据类型,api用法和redis类似
//redisTemplate.opsForSet(); // 集合
//redisTemplate.opsForZSet(); //有序集合
//redisTemplate.opsForList(); //list列表
//redisTemplate.opsForHash(); //Hash哈希
//redisTemplate.opsForValue(); //字符串
//redisTemplate.opsForGeo(); //地理位置
//redisTemplate.opsForHyperLogLog(); //基数统计
//除了基本的操作,我们常用的方法都可以通过RedisTemplate操作,比如事务和基本的CRUD(增删改查)
//redisTemplate.multi(); //事务
//获取Redis连接
//RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
// connection.flushDb(); //刷新数据库
// connection.close(); //关闭数据库
//设置字符串 尽量不要用中文(转义)
redisTemplate.opsForValue().set( "name" , "wyh" );
redisTemplate.opsForValue().set( "name1" , "魏一鹤" );
//获取字符串
System.out.println( redisTemplate.opsForValue().get( "name" ));
System.out.println( redisTemplate.opsForValue().get( "name1" ));
}
}
1 序列化配置
默认的序列化方式是JDK序列化,对字符串转义,我们可能会使用JSON来进行序列化,这时候我们就需要自己进行配置一个redisTemplate类了
2 自定义RedisTemplate(自带的不能存储中文和对象,需要我们进行更改)
例子1:创建user实体,name(中文存储到redis),age存储到redis,不进行序列化
user对象实体
package com.wyh.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* @program: SpringBoot-Redis-01
* @description: User实体
* @author: 魏一鹤
* @createDate: 2021-11-18 23:30
**/
@Data //自动get set生成(lombok依赖)
@Component //进行注入到spring工厂成为一个组件,方便我们使用
@AllArgsConstructor //生成有参构造函数(lombok依赖)
@NoArgsConstructor //生成无参构造函数(lombok依赖)
//目前我们的User实体是没有被序列化的
//想要实现序列化只需在User后加implements Serializable(实现序列化接口)
public class User {
private String name;
private int age;
}
测试方法
//注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
@Test //表示该方法是测试方法(junit依赖)
public void setUser() throws JsonProcessingException {
//真实的开发一般传递json来传递对象,而不是直接new出来对象
User user = new User( "魏一鹤" , 22);
//利用ObjectMapper把我们的User对象进行json格式化
String jsonUser = new ObjectMapper().writeValueAsString(user);
//把json格式化后的user对象以键值对应的方式存在redis中
redisTemplate.opsForValue().set( "user" ,jsonUser);
//通过key获取user对象
System.out.println( redisTemplate.opsForValue().get( "user" ));
}
打印输出
{"name":"魏一鹤","age":22}
redis中查看中文乱码
127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x04user" #中文乱码
例子2:创建user实体,name(中文存储到redis),age存储到redis,进行序列化
代码和上面类似,只不过传的对象从json变成实体,也就是没有经过json字符串转化直接传对象
@Test //表示该方法是测试方法(junit依赖)
public void setUser() throws JsonProcessingException {
//真实的开发一般传递json来传递对象,而不是直接new出来对象
User user = new User( "魏一鹤" , 22);
//利用ObjectMapper把我们的User对象进行json格式化
// String jsonUser = new ObjectMapper().writeValueAsString(user);
//把json格式化后的user对象以键值对应的方式存在redis中
//直接存储对象,而不是存储json数据类型
redisTemplate.opsForValue().set( "user" ,user);
//redisTemplate.opsForValue().set("user",jsonUser);
//通过key获取user对象
System.out.println( redisTemplate.opsForValue().get( "user" ));
}
此时会报错我们的实体User没有进行序列化
@Data *//自动get set生成(lombok依赖)*
@Component *//进行注入到spring工厂成为一个组件,方便我们使用*
@AllArgsConstructor *//生成有参构造函数(lombok依赖)*
@NoArgsConstructor *//生成无参构造函数(lombok依赖)*
*//想要实现序列化只需在User后加implements Serializable(实现序列化接口)*
*//目前企业中 我们所以的pojo(Java对象)都会进行序列化*
**public class** User **implements** Serializable {
**private** String **name**;
**private int age**;
}