目录
1 前言
2 Jedis客户端
2.1 jedis快速入门
2.2Jedis连接池
3 SpringDataRedis
3.1快速入门
3.2ReisTemplate配置序列化工具
3.3 StringRedisTemplate
在Redis官网中提供了各种语言的客户端,地址:https://redis.io/resources/clients/
因为前三个是官方推荐学习的,而第三个又是基于分布式的,不适合基础学习,所以重点学习前两个。
又因为Java中有前两个命令的整合,叫做Spring Data Redis,但有的企业又是只用到了第一个
所以,我们主要学习两个,Jedis和Spring Data Redis
Jedis的官网地址: GitHub - redis/jedis: Redis Java client designed for performance and ease of use.,我们先来个快速入门:
温馨提示:一下代码都是在单元测试里实现的哦~
1. 创建Maven工程
2. 导入Jedis客户端h和单元测试依赖:
redis.clients
jedis
3.7.0
org.junit.jupiter
junit-jupiter
5.7.0
test
3. 开始实现Jdedis客户端操作
@BeforeEach
public void setUp(){
// 1.new Jedis(ip地址,端口)
jedis = new Jedis("192.168.110.128",6379);
//2.输入密码 auth
jedis.auth("123321");
//3.选择库
jedis.select(0);
}
//redis操作
@Test
public void testString(){
String result = jedis.set("name", "Jack");
System.out.println(result);
String name = jedis.get("name");
System.out.println(name);
}
//关闭资源
@AfterEach
public void tearDown(){
//健壮性判断
if (jedis != null){
jedis.close();
}
}
最后运行结果:
完整代码如下:
package com.itheima.test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
/**
* @Author 华子
* @Date 2022/11/19 11:15
* @Version 1.0
*/
public class JedisTest {
private Jedis jedis;
//建立连接
@BeforeEach
public void setUp(){
// 1.new Jedis(ip地址,端口)
jedis = new Jedis("192.168.110.128",6379);
//2.输入密码 auth
jedis.auth("123321");
//3.选择库
jedis.select(0);
}
//redis操作
@Test
public void testString(){
String result = jedis.set("name", "Jack");
System.out.println(result);
String name = jedis.get("name");
System.out.println(name);
}
//关闭资源
@AfterEach
public void tearDown(){
//健壮性判断
if (jedis != null){
jedis.close();
}
}
}
因为Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。
连接池创建方法如下代码:
package com.itheima.jedis.util;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisFactory;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @Author 华子
* @Date 2022/11/19 11:41
* @Version 1.0
*/
public class JedisConnectFactory {
private static final JedisPool jedisPool;
static {
//1.配置连接池
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//设置最大连接池数量
jedisPoolConfig.setMaxTotal(8);
//设置最大空闲连接
jedisPoolConfig.setMaxIdle(8);
//设置最小空闲连接
jedisPoolConfig.setMinIdle(0);
//设置最大等待时间(当没有空闲连接时,等待的时间)
jedisPoolConfig.setMaxWaitMillis(1000);
//2.建立连接池(配置参数,ip地址,端口,等待时间,密码)
jedisPool = new JedisPool(jedisPoolConfig,"192.168.110.128",6379,1000,"123321");
}
//3.提供对外调用方法
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
这样连接池就创建成功啦~
而我们Jedis快速入门的时候,建立连接就变为调用这个静态类的getJedis方法了
如图:
整体代码:
package com.itheima.test;
import com.itheima.jedis.util.JedisConnectFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
/**
* @Author 华子
* @Date 2022/11/19 11:15
* @Version 1.0
*/
public class JedisTest {
private Jedis jedis;
//建立连接
@BeforeEach
public void setUp(){
// 1.new Jedis(ip地址,端口)
//jedis = new Jedis("192.168.110.128",6379);
jedis = JedisConnectFactory.getJedis();
//2.输入密码 auth
jedis.auth("123321");
//3.选择库
jedis.select(0);
}
//redis操作
@Test
public void testString(){
String result = jedis.set("name", "Jack");
System.out.println(result);
String name = jedis.get("name");
System.out.println(name);
}
//关闭资源
@AfterEach
public void tearDown(){
//健壮性判断
if (jedis != null){
jedis.close();
}
}
}
这里提一嘴,关闭资源依然是jedis.close 方法,但是,底层变成了归还线程池
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:Spring Data Redis
提供了对不同Redis客户端的整合(Lettuce和Jedis)
提供了RedisTemplate统一API来操作Redis
支持Redis的发布订阅模型
支持Redis哨兵和Redis集群
支持基于Lettuce的响应式编程
支持基于JDK.JSON.字符串.Spring对象的数据序列化及反序列化
支持基于Redis的JDKCollection实现
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:
SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单:
1.导入依赖坐标
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.5.7
com.heima
redis-demo
0.0.1-SNAPSHOT
redis-demo
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
com.fasterxml.jackson.core
jackson-databind
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
2. 配置( redis springboot中的application.yaml文件 )
spring:
redis:
host: 192.168.110.128
port: 6379
password: 123321
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 1000ms
3. 测试代码
@SpringBootTest
class RedisDemoApplicationTests {
//注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name", "虎哥");
// 获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
其实这个就是之前写入的 name:虎哥,只不过被序列化成了这个样子。
为了方便我们的可读性,还有释放内存空间,我们要对RedisTemplate进行配置序列化方式
代码如下:
package com.itheima.redis.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;
/**
* @Author 华子
* @Date 2022/11/19 19:47
* @Version 1.0
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){
//1.创建RedisTemplate
RedisTemplate redisTemplate = new RedisTemplate<>();
//2.设置连接工厂
redisTemplate.setConnectionFactory(connectionFactory);
//3.创建序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//4.设置序列化工具
//设置key
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setHashKeySerializer(RedisSerializer.string());
//设置value
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
//5.返回
return redisTemplate;
}
}
这样我们在重新运行,就会正常啦~
那么,问题来了,如果传入的是Java对象呢?能不能可以正常的序列化?
直接试一试:
新建一个实体类User
package com.itheima.redis.pojo;
import lombok.Data;
/**
* @Author 华子
* @Date 2022/11/19 19:57
* @Version 1.0
*/
@Data
public class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public User() {
}
}
传入User对象
@Test
void testObject(){
User user = new User("华子",21);
redisTemplate.opsForValue().set("user:100",user);
User userInfo = (User) redisTemplate.opsForValue().get("user:100");
System.out.println(userInfo);
}
依然可以成功序列化Json对象,并且里面还有一个参数,实体类标识,这是用于读取的时候反序列化Java对象的~
尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:
为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。
为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间
package com.itheima;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.itheima.redis.pojo.User;
import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
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;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
class StringRedisTemplateTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void testString() {
stringRedisTemplate.opsForValue().set("name","小帅");
String name = stringRedisTemplate.opsForValue().get("name");
System.out.println(name);
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("虎哥", 21);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:200", json);
// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
// 手动反序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}
}
这样就可以不用占内存啦~