SpringBoot整合Redis

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: SpringBoot整合Redis

       Redis 的常用命令在其他的文章中都已经介绍完了。作为程序员不是要在命令行中使用 Redis,毕竟我们要把 Redis 当做缓存、队列等进行使用时,因此重点还是要在代码中使用。那么,我们就需要去掌握 Redis 相关的 API 的使用方法。


Spring Boot 整合 Redis

       目前主流的 Java 项目都在使用 Spring Boot,那么我们就来在 Spring Boot 中整合 Redis。

       Spring Boot 使用“约定大于配置”的方式逐步的取代了早起通过 XML 进行配置的方式,使得在 Spring Boot 中整合各种库或者依赖都非常的方便。在我们创建 Spring Boot 项目时,选择相关的 Starter 时,在 “NoSQL” 中把 “Spring Data Redis” 项勾选即可。这样就会在 pom 文件中添加相关的依赖,依赖如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

       有了 Redis 的依赖之后,我们就可以在项目中很容易的使用 Redis 的 API 来对 Redis 进行操作了。


Redis API 介绍

       Spring Boot 提供的 Redis API 分为 高阶 API低阶 API高阶 API 是经过一定封装后的 API,而低阶 API 的使用和直接使用 Redis 的命令差不多


       高阶 API 提供了两个类可以供我们使用,分别是 RedisTemplate 和 StringRedisTemplateStringRedisTemplate 继承自 RedisTemplate,StringRedisTemplate 的序列化方式与 RedisTemplate 的序列化的方式不同。具体在使用上的差别不是特别明显,但是数据在存储到 Redis 中的时候,因为序列化方式的不同,会有一定的差别


       低阶 API 其实也是通过 RedisTemplate 或 StringRedisTemplate 来进行获取。低阶 API 的方法和 Redis 的命令差不多


Redis 高阶 API 使用

       先来看看 高阶 API 的使用方法,具体就是 RedisTemplate 和 StringRedisTemplate 两个类的使用。这里不解释具体过多的原理,主要来看看它们 API 的使用,与存储的不同。


       我们来创建一个 TestRedis 的类,并通过注解将其声明为一个 Component,并注入 RedisTemplate 和 StringRedisTemplate 两个类,代码如下。

@ComponentpublicclassTestRedis{
@AutowiredRedisTemplateredisTemplate;
@AutowiredStringRedisTemplatestringRedisTemplate;
publicvoidredis()
    {
    }
}

       我们对 Redis 的所有操作就在这个类中完成。由于我们对项目中没有引入 SpringMVC 等,因此,测试 TestRedis 就直接通过 Spring Boot 的启动类来直接进行调用,启动类的代码如下:

publicstaticvoidmain(String[] args)
{
ConfigurableApplicationContextrun=SpringApplication.run(SpringbootRedisApplication.class, args);
TestRedisbean=run.getBean(TestRedis.class);
bean.redis();
}

       我们接着来测试一下 RedisTemplate 这个类,用它来进行值为字符串的操作,代码如下:

publicvoidtestRedisTemplate()
{
ValueOperationsvalueOperations=redisTemplate.opsForValue();
valueOperations.set("key1", "value1");
valueOperations.set("key2", "哈哈");
System.out.println(valueOperations.get("key1"));
System.out.println(valueOperations.get("key2"));
}

       我们通过 redisTemplate 的 opsForValue 得到一个 ValueOperations 的实例,然后通过它来操作 Redis 的字符串类型。使用它的 set 方法添加了 key1 和 key2 两个键值对。然后,通过它的 get 方法又读取了这两个键对应的值。通过控制台的输出也可以看出,操作是成功的,控制台输出如下:

testRedisTemplate...
value1哈哈

       虽然在代码中操作是没问题的,但是,我们通过 Redis 的客户端来进行查看一下。

127.0.0.1:6379>keys*1) "\xac\xed\x00\x05t\x00\x04key2"2) "\xac\xed\x00\x05t\x00\x04key1"127.0.0.1:6379>get\xac\xed\x00\x05t\x00\x04key2(nil)

       从 Redis 的客户端查看,看到有一些 16 进制的字符,而且也不方便我们进行 get 操作。我们换一种启动 Redis 客户端的方式,在启动 Redis 客户端时,我们来加一个 --raw 的参数,再来查看我们写入的键值对,如下:

[root@node01~]#redis-cli--raw127.0.0.1:6379>keys*��tkey2��tkey1

       可以看到,在键的前面仍然有一些“奇怪”的字符,这些奇怪的字符就是前面看到的那些 16 进制字符。我们来换 StringRedisTemplate 进行相同的操作,代码如下:

publicvoidtestStringRedisTemplate()
{
ValueOperations<String, String>stringStringValueOperations=stringRedisTemplate.opsForValue();
stringStringValueOperations.set("key3", "value3");
stringStringValueOperations.set("key4", "哈哈");
System.out.println(stringStringValueOperations.get("key3"));
System.out.println(stringStringValueOperations.get("key4"));
}

       我们把前面代码注释掉,直接执行我们现在的代码,执行结果如下。

testStringRedisTemplate...
value3哈哈

       我们在到 Redis 中看一下,如下:

127.0.0.1:6379>keys*key4key3127.0.0.1:6379>getkey4哈哈127.0.0.1:6379>getkey3value3

       使用 RedisTemplate 和 StringRedisTemplate 之所以有所差异,是因为 StringRedisTemplate 在对 Key 和 Value 进行序列化时,都使用字符串的方式进行序列化。因此,我们选择 StringRedisTemplate 会方便一些。


Redis 低阶 API 使用

       Redis 的 低阶 API 使用是相对比较麻烦的。同样使用一个例子来进行查看。

publicvoidtestLowApi()
{
RedisConnectionconnection=stringRedisTemplate.getConnectionFactory().getConnection();
connection.set("key5".getBytes(), "value5".getBytes());
connection.set("key6".getBytes(), "哈哈".getBytes());
byte[] bytes=connection.get("key5".getBytes());
System.out.println(newString(bytes));
byte[] bytes1=connection.get("key6".getBytes());
System.out.println(newString(bytes1));
}

       运行代码,输出如下:

testLowApi...
value5哈哈

      同样的,我们到 Redis 的客户端中进行查看,如下:

127.0.0.1:6379>keys*key4key3key6key5127.0.0.1:6379>getkey5value5127.0.0.1:6379>getkey6哈哈

      看着效果也是不错的。不过它的操作过于繁琐,我们还是不考虑使用它。虽然不考虑使用它,但是简单的了解还是要有的。


Redis 高阶 API 操作 Hash

      在 Redis 中,使用哈希结构还是比较常见的。这里给出一个简单的操作哈希结构的代码,我们进行一些简单的操作,代码如下:

publicvoidoptHash()
{
HashOperations<String, Object, Object>stringObjectObjectHashOperations=stringRedisTemplate.opsForHash();
stringObjectObjectHashOperations.put("no1", "name", "zhangsan");
stringObjectObjectHashOperations.put("no1", "age", 22);
System.out.println(stringObjectObjectHashOperations.entries("no1"));
}

      我们来运行一下代码,运行结果如下:

optHash...
Exceptioninthread"main"java.lang.ClassCastException: java.lang.Integercannotbecasttojava.lang.Stringatorg.springframework.data.redis.serializer.StringRedisSerializer.serialize(StringRedisSerializer.java:36)
atorg.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:185)
atorg.springframework.data.redis.core.DefaultHashOperations.put(DefaultHashOperations.java:189)
atcn.coderup.TestRedis.optHash(TestRedis.java:71)
atcn.coderup.TestRedis.redis(TestRedis.java:32)
atcn.coderup.SpringbootRedisApplication.main(SpringbootRedisApplication.java:16)

       可以看到,运行代码时报错了,原因是在进行转换时发生了异常通过异常抛出的信息可以看出,在 StringRedisSerializer 进行序列化时发生的异常,这个问题是,在我们代码中的第二个 put 方法时传入了一个整型的 22 进去,这里将它改为字符串的 22,修改后的代码如下:

stringObjectObjectHashOperations.put("no1", "age", "22");

       运行修改后的代码,查看输出结果:

optHash...
{name=zhangsan, age=22}

Redis 高阶 API 操作类

       上面的代码虽然完成了对哈希的操作,但是略显繁琐,类似上面的操作我们实际中并不会去逐个的进行 put 操作,更多的应该是将一个实体类存储到 Redis 的哈希类型中。我们通过代码演示一下。


       先定义一个学生类,定义如下:

publicclassStudent{
privateStringname;
privateIntegerage;

       我省去了代码中的 getter 和 setter 方法,大家补全即可。除此而外,需要引入另外一个依赖,用于将对象转为 HashMap 或 HashMap 转换为对象。pom文件中添加的依赖如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId></dependency>

       有了上面的依赖以后,我们来接着完成代码,首先将 ObjectMapper 进行注入:

@AutowiredObjectMapperobjectMapper;

       注入 ObjectMapper 后,我们来将实体类写入 Redis 的哈希类型中,代码如下:

publicvoidoptHashForObj()
{
Studentstudent=newStudent();
student.setName("zhangsan");
student.setAge(20);
Jackson2HashMapperjackson2HashMapper=newJackson2HashMapper(objectMapper, false);
HashOperations<String, Object, Object>stringObjectObjectHashOperations=stringRedisTemplate.opsForHash();
// 对象转MapperstringObjectObjectHashOperations.putAll("no2", jackson2HashMapper.toHash(student));
Map<Object, Object>no2=stringObjectObjectHashOperations.entries("no2");
// Map转对象Studentstudent1=objectMapper.convertValue(no2, Student.class);
System.out.println(student1.getName());
System.out.println(student1.getAge());
}

      这样我们的代码看似就完成了,那么我们执行一下,看会输出什么内容,输出如下:

optHashForObj...
Exceptioninthread"main"java.lang.ClassCastException: java.lang.Integercannotbecasttojava.lang.Stringatorg.springframework.data.redis.serializer.StringRedisSerializer.serialize(StringRedisSerializer.java:36)
atorg.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:185)
atorg.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:147)
atcn.coderup.TestRedis.optHashForObj(TestRedis.java:98)
atcn.coderup.TestRedis.redis(TestRedis.java:44)
atcn.coderup.SpringbootRedisApplication.main(SpringbootRedisApplication.java:16)

      可以看出,又抛出了异常,问题同样是因为我们的 Student 类中的 age 属性是 Integer 类型。那么,是不是需要我们将 Integer 类型换成 String 类型呢?如果真的需要将 Integer 类型全部修改为 String 类型的话,那么在实际的项目中就是一场灾难了。那么具体怎么办呢?其实只要修改 Hash 的序列化器,我们在 stringRedisTemplate.opsForHash() 这句代码上增加一句代码,代码如下:

stringRedisTemplate.setHashValueSerializer(newJackson2JsonRedisSerializer<Object>(Object.class));

       再次运行我们的代码,执行结果如下:

optHashForObj...
zhangsan20

       通过 Redis 的客户端来查看我们写入的 Hash 类型的值,也是没有任何问题的。

全局的 Redis 配置

      在上面的代码中,可以通过设置 Hash 类型的序列化器从而方便的使用 putAll() 方法将一个类写入 Redis 中。但是,每次这样的写入都会特别的繁琐,我们定义一个全局的 Redis 的配置类,以后就无需每次使用都进行序列化器的设置了。


       我们添加一个 RedisConfig 类,代码如下:

@ConfigurationpublicclassRedisConfig{
@AutowiredRedisConnectionFactoryredisConnectionFactory;
@BeanpublicStringRedisTemplategetStringRedisTemplate()
    {
StringRedisTemplatestringRedisTemplate=newStringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
stringRedisTemplate.setHashValueSerializer(newJackson2JsonRedisSerializer<Object>(Object.class));
returnstringRedisTemplate;
    }
}

       有了上面的代码,我们就无需每次都设置序列化器了。为了进行测试,我们删掉前面代码中设置序列化器的代码,然后再执行代码看是否报错,结果是没有问题,不会报错。


总结

       关于在 Spring Boot 中简单整合 Redis 的方法就基本完成了。当然了,这里没有介绍具体如何操作各种数据结构的方法,以及一些 Redis 的实际使用场景,后续再进行介绍吧。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
NoSQL Java API
springboot项目Redis统计在线用户
通过本文的介绍,您可以在Spring Boot项目中使用Redis实现在线用户统计。通过合理配置Redis和实现用户登录、注销及统计逻辑,您可以高效地管理在线用户。希望本文的详细解释和代码示例能帮助您在实际项目中成功应用这一技术。
49 4
|
2月前
|
消息中间件 NoSQL Java
Spring Boot整合Redis
通过Spring Boot整合Redis,可以显著提升应用的性能和响应速度。在本文中,我们详细介绍了如何配置和使用Redis,包括基本的CRUD操作和具有过期时间的值设置方法。希望本文能帮助你在实际项目中高效地整合和使用Redis。
69 2
|
3月前
|
NoSQL Java Redis
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
这篇文章介绍了Redis的基本命令,并展示了如何使用Netty框架直接与Redis服务器进行通信,包括设置Netty客户端、编写处理程序以及初始化Channel的完整示例代码。
80 1
redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。
|
3月前
|
缓存 NoSQL Java
springboot的缓存和redis缓存,入门级别教程
本文介绍了Spring Boot中的缓存机制,包括使用默认的JVM缓存和集成Redis缓存,以及如何配置和使用缓存来提高应用程序性能。
133 1
springboot的缓存和redis缓存,入门级别教程
|
3月前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
173 2
|
3月前
|
JSON NoSQL Java
springBoot:jwt&redis&文件操作&常见请求错误代码&参数注解 (九)
该文档涵盖JWT(JSON Web Token)的组成、依赖、工具类创建及拦截器配置,并介绍了Redis的依赖配置与文件操作相关功能,包括文件上传、下载、删除及批量删除的方法。同时,文档还列举了常见的HTTP请求错误代码及其含义,并详细解释了@RequestParam与@PathVariable等参数注解的区别与用法。
|
3月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
48 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
2月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
53 0
|
3月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
90 2
|
3月前
|
存储 NoSQL Java
Spring Boot项目中使用Redis实现接口幂等性的方案
通过上述方法,可以有效地在Spring Boot项目中利用Redis实现接口幂等性,既保证了接口操作的安全性,又提高了系统的可靠性。
68 0