笔记
使用工具
介绍
Jedis
1.引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2.测试
@SpringBootTest
class WebTestApplicationTests {
private Jedis jedis;
@BeforeEach
void setUp(){
//建立连接
jedis = new Jedis("192.168.137.128", 6379);
//设置密码
jedis.auth("123456");
//选择库
jedis.select(0);
}
@Test
void testString(){
//存入数据
String result = jedis.set("name1","scy");
System.out.println("result = " + result);
String out = jedis.get("name1");
System.out.println("out = " + out);
}
@AfterEach
void tearDown(){
if(jedis != null){
jedis.close();
}
}
}
Jedis连接池
虽然使用简单,但Jedis实例本身线程不安全,多线程环境下需要使用Jedis线程池
来替代Jedis
配置连接池
-
JedisConnectionFactory有一个静态方法getJedis,返回一个Jedis实例
-
配置的顺序是:JedisPoolConfig——JedisPool——getResource()返回Jedis实例
连接池JedisConnectionFactory如下:
public class JedisConnectionFactory {
//在static静态代码块中初始化
private static final JedisPool pool;
//静态代码块,随类的加载而加载
static{
//1.jedis连接池配置类
JedisPoolConfig config = new JedisPoolConfig();
//1.1可用连接实例的最大数目,默认值为8;
config.setMaxTotal(10);
//1.2控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值8。
//设置没人访问时,最多有5个空闲;设置太大占内存
config.setMaxIdle(5);
//1.3pool的最小idle数,默认为8
//设置没人访问时,释放连接数的底线;设置太小无法快速应对突然的请求
config.setMinIdle(3);
//1.4设置最长等待时间,当池中没有线程可用时,超出时间就报错
//-1表示无限等待,这里设置为1000ms
config.setMaxWaitMillis(1000);
//2.创建连接池对象,形参为(上面的配置类对象config,ip,端口,连接超时时间,密码)
pool = new JedisPool(config, "xxx.xxx.xxx.xxx", 6379, 1000, "xxxxxxxx");
}
//3.静态方法:从pool中获取一个资源(实例)
public static Jedis getJedis(){
return pool.getResource();
}
使用连接池
- 之前用new Jedis,现在是使用连接池获取
- 之前是直接关闭Jedis,现在是把Jedis归还给连接池
SpringDataRedis——RedisTemplate
快速入门
springboot默认的是lettuce依赖,所以使用lettuce作为连接池时不需要Jedis依赖;但如果是想使用Jedis作为连接池,就需要引入之前的Jedis依赖
1.引入依赖
<!--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>
</dependency>
2.配置文件
3.注入
@Autowired
private RedisTemplate redisTemplate;
4.测试
@Test
void testString(){
//插入数据
redisTemplate.opsForValue().set("name", "scy");
//获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = "+ name);
}
问题发生
乱码出现
问题分析
由于我们并没有对工具类RedisTemplate进行任何修改而直接使用,因此我们进入源码进行分析
默认序列化器defaultSerializer = null ;
默认使用JDK序列化器
JDK序列化器JdkSerializationRedisSerializer的内核是对象流:把对象存储为字节码的形式,而不是文本,因此看到的必然乱码,同理用对象流保存数据到txt文件中也会乱码
解决问题
JDK的序列化器协议不是JSON,因此我们需要一个能传JSON字符串的序列化器
既然是因为底层用了JDK序列化器JdkSerializationRedisSerializer,使用的对象流,那么我们只需
要改变RedisTemplate的序列化器RedisSerializer,例如:StringRedisSerializer、GenericJackson2JsonRedisSerializer
补充
- JDK序列化:底层是对象流(字节流),传输到redis上人类看不懂
- XML序列化:人类可读性强,底层是 字节流传输+xml解析
- JSON序列化:跨平台,可读性强,底层是 字节流传输+JSON解析
- FastJSON序列化:JSON的高性能库
-
jdk的序列化,就是序列化成字节流通过网络传输到redis里面存起来,但是你查出来的就是直接序列化的你看不懂的字节流的形式,默认是十六进制数据
-
而其他满足JSON协议的序列化器,序列化成字节流通过网络传输到redis里面存起来的同时,还可以转化为字符串,让人类能够看得懂,本质上还是序列化
解决乱码问题
方案一:RedisTemplate
- StringRedisSerializer:用于序列化String(Key和hashKey),并且传输之后能正确显示为String
- GenericJackson2JsonRedisSerializer: 满足JSON协议,用于序列化对象(value和hashValue)
方案二:StringRedisTemplate
方案三:FastJSON+StringRedisTemplate
介绍
- 利用Fastjson把对象——>String字符串
- 利用Spring提供的StringRedisTemplate来把String字符串——>传输到redis,并且不乱码
StringRedisTemplate本质是一个配置好String序列化器的RedisTemplate
下载Fastjson的jar包并导入
测试
Managers managers = new Managers();
managers.setSex("男");
managers.setAge(18);
managers.setName("张三");
String s = JSON.toJSONString(managers);
System.out.println(s);
使用
- 直接注入StringRedisTemplate即可,配置信息在application.yaml中
- ON即fastjson的工具类,主要调用toJSONString()和parseObject(,)两个方法
- 因为只对String进行操作,所以只需要opsForValue()即可:stringRedisTemplate.opsForValue().set()或.get()
@SpringBootTest
class BootAjaxtestApplicationTests {
//1.注入String序列化模板
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
public void test1(){
Managers managers = new Managers();
managers.setSex("男");
managers.setAge(18);
managers.setName("张三");
//2.fastjson序列化对象
String s = JSON.toJSONString(managers);
//3.写入数据到redis
stringRedisTemplate.opsForValue().set("test张三", s);
//4.读取数据并反序列化
String r = stringRedisTemplate.opsForValue().get("test张三");
Managers managers1 = JSON.parseObject(r, Managers.class);
System.out.println(managers1);//Managers(name=张三, sex=男, age=18)
}}