快速入门
导入依赖
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
测试代码
package com.example;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
public class JedisTest {
private Jedis jedis;
@BeforeEach
void setUp() {
jedis = new Jedis("192.168.168.168", 6379);
jedis.auth("123456");
jedis.select(0);
}
@Test
void test() {
String name = jedis.get("name");
System.out.println(name);
}
@AfterEach
void tearDown() {
if(jedis != null){
jedis.close();
}
}
}
jedis连接池
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐大家使用Jedis连接池代替Jedis的直连方式。
package com.example.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisConnectionFactory {
private static JedisPool jedisPool;
//在类加载时执行
static {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);//最大连接数
poolConfig.setMaxIdle(8);//最大空闲连接数
poolConfig.setMinIdle(0);//最小空闲连接数
poolConfig.setMaxWaitMillis(1000);//最大等待时间 (单位:毫秒)
jedisPool = new JedisPool(poolConfig, "192.168.168.168", 6379, 1000, "123456");
}//连接超时时间 1000毫秒
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
修改后这样获取jedis对象
@BeforeEach
void setUp() {
jedis = JedisConnectionFactory.getJedis();
jedis.auth("123456");
jedis.select(0);
}
SpringDataRedis
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:Spring Data Redis
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
快速入门
导入依赖
<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>
配置redis
spring:
data:
redis:
host: 192.168.168.168
port: 6379
password: 123456
database: 0
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
测试
package com.example;
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.core.RedisTemplate;
@SpringBootTest
public class RedisTemplateTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test01() {
redisTemplate.opsForValue().set("name","lihua");
System.out.println(redisTemplate.opsForValue().get("name"));
}
}
自定义序列化
jdk序列化(默认的序列化方式)的问题
进行如上测试后,发现并没有修改key为name的值为lihua,而是出现了这样的结果
原因如下
RedisTemplate可以接收任意Object作为值写入Redis:
只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:
- 可读性差
- 内存占用较大
***************************************************
自定义序列化方式为json序列化
首先写一个RedisTemplate的配置
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisTemplateConfig {
@Bean
//RedisConnectionFactory是spring内置的,在项目启动时会自动装配,因此作为参数传入即可
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
//创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
//设置连接工厂
template.setConnectionFactory(factory);
//创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//设置key的序列化 RedisSerializer是redis的一个序列化器
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//设置value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
//返回
return template;
}
}
在springboot项目启动时,这个bean就会被加载
重新测试
@Test
public void test01() {
redisTemplate.opsForValue().set("name","zhaosi");
System.out.println(redisTemplate.opsForValue().get("name"));
}
测试结果如下
符合我们的预期
*********************************
也可以存入自定义对象
@Test
public void test02() {
User u1 = new User(1, "laoda", 24);
redisTemplate.opsForValue().set("user:001", u1);
}
@Test
public void test03() {
User user = (User) redisTemplate.opsForValue().get("user:001");
System.out.println(user);
}
测试结果如下
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。 (我们将用StringRedisTemplate进行改进)
SpringRedisTemplate
为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器(这样value就不用存储对象的字节码文件了),要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。
因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。
导入jackson依赖
<!--Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用就好了
@SpringBootTest
public class StringRedisTemplateTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final ObjectMapper mapper = new ObjectMapper();
@Test
public void test() throws JsonProcessingException {
User u1 = new User(2, "赵四", 25);
//手动序列化
String json = mapper.writeValueAsString(u1);
System.out.println("序列化后的json字符串:"+json);
//写入数据
stringRedisTemplate.opsForValue().set("user:002",json);
//获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:002");
//反序列化
User user = mapper.readValue(jsonUser, User.class);
System.out.println("反序列化得到的结果:"+user);
}
}
可以看到,里面是没有对象的字节码的