• Redis的Java客户端


    目录

    1 前言

    2 Jedis客户端

    2.1 jedis快速入门 

     2.2Jedis连接池

    3 SpringDataRedis

    3.1快速入门 

    3.2ReisTemplate配置序列化工具

    3.3 StringRedisTemplate 


    1 前言

    Redis官网中提供了各种语言的客户端,地址:https://redis.io/resources/clients/

     

    因为前三个是官方推荐学习的,而第三个又是基于分布式的,不适合基础学习,所以重点学习前两个。

    又因为Java中有前两个命令的整合,叫做Spring Data Redis,但有的企业又是只用到了第一个

     所以,我们主要学习两个,Jedis和Spring Data Redis

    2 Jedis客户端

    2.1 jedis快速入门 

    Jedis的官网地址: GitHub - redis/jedis: Redis Java client designed for performance and ease of use.,我们先来个快速入门:

    温馨提示:一下代码都是在单元测试里实现的哦~

    1. 创建Maven工程

    2. 导入Jedis客户端h和单元测试依赖:

    1. <dependencies>
    2. <dependency>
    3. <groupId>redis.clientsgroupId>
    4. <artifactId>jedisartifactId>
    5. <version>3.7.0version>
    6. dependency>
    7. <dependency>
    8. <groupId>org.junit.jupitergroupId>
    9. <artifactId>junit-jupiterartifactId>
    10. <version>5.7.0version>
    11. <scope>testscope>
    12. dependency>
    13. dependencies>

    3.  开始实现Jdedis客户端操作

    • 建立连接
      1. @BeforeEach
      2. public void setUp(){
      3. // 1.new Jedis(ip地址,端口)
      4. jedis = new Jedis("192.168.110.128",6379);
      5. //2.输入密码 auth
      6. jedis.auth("123321");
      7. //3.选择库
      8. jedis.select(0);
      9. }
    • 编写Redis操作(String类型操作)
      1. //redis操作
      2. @Test
      3. public void testString(){
      4. String result = jedis.set("name", "Jack");
      5. System.out.println(result);
      6. String name = jedis.get("name");
      7. System.out.println(name);
      8. }
    • 关闭资源
      1. //关闭资源
      2. @AfterEach
      3. public void tearDown(){
      4. //健壮性判断
      5. if (jedis != null){
      6. jedis.close();
      7. }
      8. }

    最后运行结果:

     完整代码如下:

    1. package com.itheima.test;
    2. import org.junit.jupiter.api.AfterEach;
    3. import org.junit.jupiter.api.BeforeEach;
    4. import org.junit.jupiter.api.Test;
    5. import redis.clients.jedis.Jedis;
    6. /**
    7. * @Author 华子
    8. * @Date 2022/11/19 11:15
    9. * @Version 1.0
    10. */
    11. public class JedisTest {
    12. private Jedis jedis;
    13. //建立连接
    14. @BeforeEach
    15. public void setUp(){
    16. // 1.new Jedis(ip地址,端口)
    17. jedis = new Jedis("192.168.110.128",6379);
    18. //2.输入密码 auth
    19. jedis.auth("123321");
    20. //3.选择库
    21. jedis.select(0);
    22. }
    23. //redis操作
    24. @Test
    25. public void testString(){
    26. String result = jedis.set("name", "Jack");
    27. System.out.println(result);
    28. String name = jedis.get("name");
    29. System.out.println(name);
    30. }
    31. //关闭资源
    32. @AfterEach
    33. public void tearDown(){
    34. //健壮性判断
    35. if (jedis != null){
    36. jedis.close();
    37. }
    38. }
    39. }

     2.2Jedis连接池

    因为Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。

    连接池创建方法如下代码:

    1. package com.itheima.jedis.util;
    2. import redis.clients.jedis.Jedis;
    3. import redis.clients.jedis.JedisFactory;
    4. import redis.clients.jedis.JedisPool;
    5. import redis.clients.jedis.JedisPoolConfig;
    6. /**
    7. * @Author 华子
    8. * @Date 2022/11/19 11:41
    9. * @Version 1.0
    10. */
    11. public class JedisConnectFactory {
    12. private static final JedisPool jedisPool;
    13. static {
    14. //1.配置连接池
    15. JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
    16. //设置最大连接池数量
    17. jedisPoolConfig.setMaxTotal(8);
    18. //设置最大空闲连接
    19. jedisPoolConfig.setMaxIdle(8);
    20. //设置最小空闲连接
    21. jedisPoolConfig.setMinIdle(0);
    22. //设置最大等待时间(当没有空闲连接时,等待的时间)
    23. jedisPoolConfig.setMaxWaitMillis(1000);
    24. //2.建立连接池(配置参数,ip地址,端口,等待时间,密码)
    25. jedisPool = new JedisPool(jedisPoolConfig,"192.168.110.128",6379,1000,"123321");
    26. }
    27. //3.提供对外调用方法
    28. public static Jedis getJedis(){
    29. return jedisPool.getResource();
    30. }
    31. }

    这样连接池就创建成功啦~

    而我们Jedis快速入门的时候,建立连接就变为调用这个静态类的getJedis方法了

    如图:

    整体代码:

    1. package com.itheima.test;
    2. import com.itheima.jedis.util.JedisConnectFactory;
    3. import org.junit.jupiter.api.AfterEach;
    4. import org.junit.jupiter.api.BeforeEach;
    5. import org.junit.jupiter.api.Test;
    6. import redis.clients.jedis.Jedis;
    7. /**
    8. * @Author 华子
    9. * @Date 2022/11/19 11:15
    10. * @Version 1.0
    11. */
    12. public class JedisTest {
    13. private Jedis jedis;
    14. //建立连接
    15. @BeforeEach
    16. public void setUp(){
    17. // 1.new Jedis(ip地址,端口)
    18. //jedis = new Jedis("192.168.110.128",6379);
    19. jedis = JedisConnectFactory.getJedis();
    20. //2.输入密码 auth
    21. jedis.auth("123321");
    22. //3.选择库
    23. jedis.select(0);
    24. }
    25. //redis操作
    26. @Test
    27. public void testString(){
    28. String result = jedis.set("name", "Jack");
    29. System.out.println(result);
    30. String name = jedis.get("name");
    31. System.out.println(name);
    32. }
    33. //关闭资源
    34. @AfterEach
    35. public void tearDown(){
    36. //健壮性判断
    37. if (jedis != null){
    38. jedis.close();
    39. }
    40. }
    41. }

    这里提一嘴,关闭资源依然是jedis.close 方法,但是,底层变成了归还线程池

     

    3 SpringDataRedis

    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封装到了不同的类型中:

    3.1快速入门 

     SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单:

    1.导入依赖坐标

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <parent>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-parentartifactId>
    8. <version>2.5.7version>
    9. <relativePath/>
    10. parent>
    11. <groupId>com.heimagroupId>
    12. <artifactId>redis-demoartifactId>
    13. <version>0.0.1-SNAPSHOTversion>
    14. <name>redis-demoname>
    15. <description>Demo project for Spring Bootdescription>
    16. <properties>
    17. <java.version>1.8java.version>
    18. properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-starter-data-redisartifactId>
    23. dependency>
    24. <dependency>
    25. <groupId>org.apache.commonsgroupId>
    26. <artifactId>commons-pool2artifactId>
    27. dependency>
    28. <dependency>
    29. <groupId>com.fasterxml.jackson.coregroupId>
    30. <artifactId>jackson-databindartifactId>
    31. dependency>
    32. <dependency>
    33. <groupId>org.projectlombokgroupId>
    34. <artifactId>lombokartifactId>
    35. <optional>trueoptional>
    36. dependency>
    37. <dependency>
    38. <groupId>org.springframework.bootgroupId>
    39. <artifactId>spring-boot-starter-testartifactId>
    40. <scope>testscope>
    41. dependency>
    42. dependencies>
    43. <build>
    44. <plugins>
    45. <plugin>
    46. <groupId>org.springframework.bootgroupId>
    47. <artifactId>spring-boot-maven-pluginartifactId>
    48. <configuration>
    49. <excludes>
    50. <exclude>
    51. <groupId>org.projectlombokgroupId>
    52. <artifactId>lombokartifactId>
    53. exclude>
    54. excludes>
    55. configuration>
    56. plugin>
    57. plugins>
    58. build>
    59. project>

    2. 配置( redis springboot中的application.yaml文件 )

    1. spring:
    2. redis:
    3. host: 192.168.110.128
    4. port: 6379
    5. password: 123321
    6. lettuce:
    7. pool:
    8. max-active: 8
    9. max-idle: 8
    10. min-idle: 0
    11. max-wait: 1000ms

    3. 测试代码

    1. @SpringBootTest
    2. class RedisDemoApplicationTests {
    3. //注入RedisTemplate
    4. @Autowired
    5. private RedisTemplate redisTemplate;
    6. @Test
    7. void testString() {
    8. // 写入一条String数据
    9. redisTemplate.opsForValue().set("name", "虎哥");
    10. // 获取string数据
    11. Object name = redisTemplate.opsForValue().get("name");
    12. System.out.println("name = " + name);
    13. }
    14. }

    3.2ReisTemplate配置序列化工具

    RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

    其实这个就是之前写入的 name:虎哥,只不过被序列化成了这个样子。

    为了方便我们的可读性,还有释放内存空间,我们要对RedisTemplate进行配置序列化方式

    代码如下:

    1. package com.itheima.redis.config;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.data.redis.connection.RedisConnectionFactory;
    5. import org.springframework.data.redis.core.RedisTemplate;
    6. import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    7. import org.springframework.data.redis.serializer.RedisSerializer;
    8. /**
    9. * @Author 华子
    10. * @Date 2022/11/19 19:47
    11. * @Version 1.0
    12. */
    13. @Configuration
    14. public class RedisConfig {
    15. @Bean
    16. public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory){
    17. //1.创建RedisTemplate
    18. RedisTemplate redisTemplate = new RedisTemplate<>();
    19. //2.设置连接工厂
    20. redisTemplate.setConnectionFactory(connectionFactory);
    21. //3.创建序列化工具
    22. GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
    23. //4.设置序列化工具
    24. //设置key
    25. redisTemplate.setKeySerializer(RedisSerializer.string());
    26. redisTemplate.setHashKeySerializer(RedisSerializer.string());
    27. //设置value
    28. redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
    29. redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
    30. //5.返回
    31. return redisTemplate;
    32. }
    33. }

     这样我们在重新运行,就会正常啦~

    那么,问题来了,如果传入的是Java对象呢?能不能可以正常的序列化?

    直接试一试:

    新建一个实体类User

    1. package com.itheima.redis.pojo;
    2. import lombok.Data;
    3. /**
    4. * @Author 华子
    5. * @Date 2022/11/19 19:57
    6. * @Version 1.0
    7. */
    8. @Data
    9. public class User {
    10. private String name;
    11. private Integer age;
    12. public User(String name, Integer age) {
    13. this.name = name;
    14. this.age = age;
    15. }
    16. public User() {
    17. }
    18. }

    传入User对象 

    1. @Test
    2. void testObject(){
    3. User user = new User("华子",21);
    4. redisTemplate.opsForValue().set("user:100",user);
    5. User userInfo = (User) redisTemplate.opsForValue().get("user:100");
    6. System.out.println(userInfo);
    7. }

    依然可以成功序列化Json对象,并且里面还有一个参数,实体类标识,这是用于读取的时候反序列化Java对象的~

    3.3 StringRedisTemplate 

    尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:

    为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。 

     为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间

     代码就变成了如下方式(添加了手动序列化和反序列化)

    1. package com.itheima;
    2. import com.fasterxml.jackson.core.JsonProcessingException;
    3. import com.fasterxml.jackson.databind.ObjectMapper;
    4. import com.fasterxml.jackson.databind.ObjectWriter;
    5. import com.itheima.redis.pojo.User;
    6. import net.minidev.json.JSONObject;
    7. import net.minidev.json.JSONValue;
    8. import org.junit.jupiter.api.Test;
    9. import org.springframework.beans.factory.annotation.Autowired;
    10. import org.springframework.boot.test.context.SpringBootTest;
    11. import org.springframework.data.redis.core.RedisTemplate;
    12. import org.springframework.data.redis.core.StringRedisTemplate;
    13. @SpringBootTest
    14. class StringRedisTemplateTest {
    15. @Autowired
    16. private StringRedisTemplate stringRedisTemplate;
    17. @Test
    18. void testString() {
    19. stringRedisTemplate.opsForValue().set("name","小帅");
    20. String name = stringRedisTemplate.opsForValue().get("name");
    21. System.out.println(name);
    22. }
    23. private static final ObjectMapper mapper = new ObjectMapper();
    24. @Test
    25. void testSaveUser() throws JsonProcessingException {
    26. // 创建对象
    27. User user = new User("虎哥", 21);
    28. // 手动序列化
    29. String json = mapper.writeValueAsString(user);
    30. // 写入数据
    31. stringRedisTemplate.opsForValue().set("user:200", json);
    32. // 获取数据
    33. String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
    34. // 手动反序列化
    35. User user1 = mapper.readValue(jsonUser, User.class);
    36. System.out.println("user1 = " + user1);
    37. }
    38. }

    这样就可以不用占内存啦~ 

  • 相关阅读:
    TatukGIS Developer Kernel使用教程:如何为FMX创建第一个应用程序
    leetcode 21
    GBase 8c 存储技术---列存储引擎(二)
    spring boot + mybaties-plus 数据库字段加解密
    spring 5.1.x 本地构建 build.gradle文件配置
    摘要-签名-PKI-访问控制-DOS-欺骗技术
    Android开发基础——ListView
    LeetCode回溯算法组合问题——216.组合总和III
    区块链 - 各个国家Web3的现状与趋势
    一文读懂OpenAI文生视频模型Sora原理
  • 原文地址:https://blog.csdn.net/qq_59212867/article/details/127934658