目录
在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和单元测试依赖:
- <dependencies>
-
- <dependency>
- <groupId>redis.clientsgroupId>
- <artifactId>jedisartifactId>
- <version>3.7.0version>
- dependency>
-
- <dependency>
- <groupId>org.junit.jupitergroupId>
- <artifactId>junit-jupiterartifactId>
- <version>5.7.0version>
- <scope>testscope>
- dependency>
- dependencies>
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.导入依赖坐标
- "1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
- <parent>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-parentartifactId>
- <version>2.5.7version>
- <relativePath/>
- parent>
- <groupId>com.heimagroupId>
- <artifactId>redis-demoartifactId>
- <version>0.0.1-SNAPSHOTversion>
- <name>redis-demoname>
- <description>Demo project for Spring Bootdescription>
- <properties>
- <java.version>1.8java.version>
- properties>
- <dependencies>
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-redisartifactId>
- dependency>
-
- <dependency>
- <groupId>org.apache.commonsgroupId>
- <artifactId>commons-pool2artifactId>
- dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- dependency>
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <optional>trueoptional>
- dependency>
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-testartifactId>
- <scope>testscope>
- dependency>
- dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-maven-pluginartifactId>
- <configuration>
- <excludes>
- <exclude>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- exclude>
- excludes>
- configuration>
- plugin>
- plugins>
- build>
-
- project>
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);
- }
-
- }
这样就可以不用占内存啦~
