Redis的java客户端

spring整合了前三种我们只需要学习spring整合的就行了。不过还是有企业使用老一套的原生的jedis。
jedis
操作
引入依赖
java
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
建立连接
java
private Jedis jedis;
@BeforeEach
void setUp() {
// 建立连接
jedis = new Jedis("192.168.150.101", 6379);
// 设置密码
jedis.auth("123321");
// 选择库
jedis.select(0);
}
测试
java
@Test
void testString() {
// 插入数据,方法名称就是 redis 命令名称,非常简单
String result = jedis.set("name", "张三");
System.out.println("result = " + result);
// 获取数据
String name = jedis.get("name");
System.out.println("name = " + name);
}
释放
java
@AfterEach
void tearDown() {
// 释放资源
if (jedis != null) {
jedis.close();
}
}
jedis连接池
因为是jedis是单线程,所以一但出现多线程调用一个实例就会出现线程安全问题,而且频繁的创建和销毁对象实例是有很大的性能损耗,所以我们需要设置多个实例交给连接池来管理。
java
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
// 最大连接
jedisPoolConfig.setMaxTotal(8);
// 最大空闲连接
jedisPoolConfig.setMaxIdle(8);
// 最小空闲连接
jedisPoolConfig.setMinIdle(0);
// 设置最长等待时间,ms
jedisPoolConfig.setMaxWaitMillis(200);
jedisPool = new JedisPool(jedisPoolConfig, "192.168.150.101", 6379, 1000, "123321");
}
// 获取Jedis对象
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
这个代码里面有static代码块,这是一个静态代码块 。它里面的代码会在类被加载到 JVM 时执行一次 ,并且只执行一次 。它在任何对象创建之前,甚至在 main
方法执行之前就可能被执行。用来初始化 static
的 jedisPool
。当 JedisConnectionFactory
类第一次被使用(比如调用 getJedis()
方法)时,JVM 会加载这个类,并自动执行这个静态代码块,完成连接池的配置和创建。之后,这个创建好的 jedisPool
就可以被所有地方共享使用了。
这里提供一个简单、全局的入口点来获取 Jedis 连接。使用者不需要关心 JedisConnectionFactory
的内部细节,也不需要自己去创建这个工厂类的对象,直接调用 JedisConnectionFactory.getJedis()
就能得到一个连接。这是一种常见的"工厂模式"或"工具类"设计。
SpringDataRedis

操作

引入依赖
springboot里面引入了SpringDataRedis这个依赖不用手动导包。
连接池需要自己导入。
java
<!-- 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>
配置文件
java
spring:
redis:
host: 192.168.150.101
port: 6379
password: 123321
lettuce:
pool:
max-active: 8 # 最大连接
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 100 # 连接等待时间
spring默认连接池实现的是lettuce,如果要用jedis还需要自己手动导入依赖。
注入
java
@Autowired
private RedisTemplate<String, Object> redisTemplate;
测试
java
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testString() {
// 插入一条string类型数据
redisTemplate.opsForValue().set("name", "李四");
// 读取一条string类型数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
序列化
spring里面接受的是object对象,接受之后会用序列化器把对象序列化字节形式传递给底层的jedis。

改变序列化方式

序列化器的实现类有多个,我们选择专门处理字符串的就行。
一般,如果key是字符串,我们就是用字符串序列化,值如果是对象我们就使用json序列化。
操作
java
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
// 创建 Template
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;
}
这个bean需要写在一个新的spring配置文件里面。
还需要额外引入jackson依赖,平常开发的话springmvc里面自带了。
类地址的自动填入问题
解决办法


java
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testStringRedisTemplate() throws JsonProcessingException {
// 准备对象
User user = new User("虎哥", 18);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入一条数据到redis
stringRedisTemplate.opsForValue().set("user:200", json);
// 读取数据
String val = stringRedisTemplate.opsForValue().get("user:200");
// 反序列化
User user1 = mapper.readValue(val, User.class);
System.out.println("user1 = " + user1);
}