当前位置: 首页 > news >正文

Redis中的Java客户端

一、Jedis

Jedis是一个Java实现的Redis客户端连接工具。

Jedis使用非常简单,直接引入依赖。基于默认参数的Jedis连接池,初始化连接池类(使用默认连接池参数)JedisPool,获取一个Jedis连接Jedis jedis=jp.getResource()。

Jedis是线程不安全的,多线程使用同一个Jedis实例,会出现并发问题,原因是底层共用了一个输入输出流

1.1  Jedis快速入门

Jedis的官网地址: GitHub - redis/jedis: Redis Java client,我们先来个快速入门:

① 新建一个Maven工程并引入以下依赖  

<!--引入Jedis依赖-->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.0</version>
</dependency><!--引入单元测试依赖-->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>test</scope>
</dependency>

② 编写测试类并与Redis建立连接

private Jedis jedis;@BeforeEach //被该注解修饰的方法每次执行其他方法前自动执行
void setUp(){// 1. 获取连接jedis = new Jedis("192.168.230.88",6379);// 2. 设置密码jedis.auth("132537");// 3. 选择库(默认是下标为0的库)jedis.select(0);
}

③ 编写一个操作数据的方法(这里以操作String类型为例)

@Test
public void testString(){// 1.往redis中存放一条String类型的数据并获取返回结果String result = jedis.set("url", "https://www.oz6.cn");System.out.println("result = " + result);// 2.从redis中获取一条数据String url = jedis.get("url");System.out.println("url = " + url);
}

④ 最后不要忘记编写一个释放资源的方法

    @AfterEach //被该注解修饰的方法会在每次执行其他方法后执行void tearDown(){// 1.释放资源if (jedis != null){jedis.close();}}

⑤ 执行testString()方法后测试结果如图所示

1.2  Jedis连接池

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

public class JedisConnectionFactory {private static final JedisPool jedisPool;static {//配置连接池JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxTotal(8);jedisPoolConfig.setMaxIdle(8);jedisPoolConfig.setMinIdle(0);jedisPoolConfig.setMaxWaitMillis(200);//创建连接池对象jedisPool = new JedisPool(jedisPoolConfig,"192.168.230.88",6379,1000,"132537");}public static Jedis getJedis(){return jedisPool.getResource();}
}

二、SpringDataRedis介绍

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

官网地址:Spring Data Redis

  • 提供了对不同Redis客户端的整合(LettuceJedis

  • 提供了RedisTemplate统一API来操作Redis

  • 支持Redis的发布订阅模型

  • 支持Redis哨兵和Redis集群

  • 支持基于Lettuce的响应式编程

  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化

  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

三、SpringDataRedis快速入门

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

① 首先新建一个Spring Boot工程

② 然后引入连接池依赖

<!--连接池依赖-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>
</dependency>

③ 编写配置文件application.yml(连接池的配置在实际开发中是根据需求来的)

spring:redis:host: 192.168.230.88 #指定redis所在的hostport: 6379  #指定redis的端口password: 132537  #设置redis密码lettuce:pool:max-active: 8 #最大连接数max-idle: 8 #最大空闲数min-idle: 0 #最小空闲数max-wait: 100ms #连接等待时间

④ 编写测试类执行测试方法

@SpringBootTest
class RedisDemoApplicationTests {@Resourceprivate RedisTemplate redisTemplate;@Testvoid testString() {// 1.通过RedisTemplate获取操作String类型的ValueOperations对象ValueOperations ops = redisTemplate.opsForValue();// 2.插入一条数据ops.set("blogName","Vz-Blog");// 3.获取数据String blogName = (String) ops.get("blogName");System.out.println("blogName = " + blogName);}
}

四、RedisSerializer配置

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

缺点:

  • 可读性差

  • 内存占用较大

那么如何解决以上的问题呢?我们可以通过自定义RedisTemplate序列化的方式来解决。

编写一个配置类RedisConfig :

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){// 1.创建RedisTemplate对象RedisTemplate<String ,Object> redisTemplate = new RedisTemplate<>();// 2.设置连接工厂redisTemplate.setConnectionFactory(factory);// 3.创建序列化对象StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 4.设置key和hashKey采用String的序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);redisTemplate.setHashKeySerializer(stringRedisSerializer);// 5.设置value和hashValue采用json的序列化方式redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);return redisTemplate;}
}

此时我们已经将RedisTemplate的key设置为String序列化,value设置为Json序列化的方式,再来执行方法测试

由于我们设置的value序列化方式是Json的,因此我们可以直接向redis中插入一个对象

@Test
void testSaveUser() {redisTemplate.opsForValue().set("user:100", new User("Vz", 21));User user = (User) redisTemplate.opsForValue().get("user:100");System.out.println("User = " + user);
}

尽管Json序列化可以满足我们的需求,但是依旧存在一些问题。

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

那么我们如何解决这个问题呢?我们可以通过下文的StringRedisTemplate来解决这个问题。

五、StringRedisTemplate

为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程

我们可以直接编写一个测试类使用StringRedisTemplate来执行以下方法:

@SpringBootTest
class RedisStringTemplateTest {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Testvoid testSaveUser() throws JsonProcessingException {// 1.创建一个Json序列化对象ObjectMapper objectMapper = new ObjectMapper();// 2.将要存入的对象通过Json序列化对象转换为字符串String userJson1 = objectMapper.writeValueAsString(new User("Vz", 21));// 3.通过StringRedisTemplate将数据存入redisstringRedisTemplate.opsForValue().set("user:100",userJson1);// 4.通过key取出valueString userJson2 = stringRedisTemplate.opsForValue().get("user:100");// 5.由于取出的值是String类型的Json字符串,因此我们需要通过Json序列化对象来转换为java对象User user = objectMapper.readValue(userJson2, User.class);// 6.打印结果System.out.println("user = " + user);}}

执行完毕回到Redis的图形化客户端查看结果

六、总结

RedisTemplate的两种序列化实践方案,两种方案各有各的优缺点,可以根据实际情况选择使用。

方案一:

  1. 自定义RedisTemplate

  2. 修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer

方案二:

  1. 使用StringRedisTemplate

  2. 写入Redis时,手动把对象序列化为JSON

  3. 读取Redis时,手动把读取到的JSON反序列化为对象

相关文章:

  • 设计模式——适配器模式
  • 通过代理连接sftp
  • 汇编和C语言转换
  • 深入理解Lock Support
  • 2024年01月微软更新Bug 已解决 !Explorer.EXE 提示:Windows无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目。
  • 测绘资质工程测量乙级资质办理条件
  • 强力推荐:本地文件加密软件—超详细加密步骤来了!
  • 概念解析 | 感知世界的无形之“波”:WiFi感知中的信道状态信息(CSI)探秘
  • 【Golang】十六进制字符串转二进制字符串
  • vue前端开发自学,插槽练习第二次,name属性的使用
  • OpenWrt智能路由器Wan PPPoE拨号配置方法
  • [开发语言][c++][python]:C++与Python中的赋值、浅拷贝与深拷贝
  • RGB,RGB-D,单目,双目,sterro相机,实例相机介绍
  • 独孤思维:​凌驾于所有赚钱项目的副业
  • iOS 位移枚举NS_OPTIONS(如何实现多个枚举值的同时传入判断)
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Angular Elements 及其运作原理
  • IDEA 插件开发入门教程
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • js
  • linux安装openssl、swoole等扩展的具体步骤
  • nodejs:开发并发布一个nodejs包
  • v-if和v-for连用出现的问题
  • vue-cli在webpack的配置文件探究
  • vue-loader 源码解析系列之 selector
  • windows-nginx-https-本地配置
  • windows下mongoDB的环境配置
  • 对JS继承的一点思考
  • 复习Javascript专题(四):js中的深浅拷贝
  • 回顾2016
  • 前端攻城师
  • 少走弯路,给Java 1~5 年程序员的建议
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 正则与JS中的正则
  • const的用法,特别是用在函数前面与后面的区别
  • PostgreSQL之连接数修改
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • Semaphore
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • # 飞书APP集成平台-数字化落地
  • ###STL(标准模板库)
  • #1014 : Trie树
  • (rabbitmq的高级特性)消息可靠性
  • (待修改)PyG安装步骤
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (十) 初识 Docker file
  • (一)Linux+Windows下安装ffmpeg
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • .net 按比例显示图片的缩略图
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径