准备工作
-
如果Redis是在远程或者在linux虚拟机中,需要先关闭防火墙,或者将Redis服务运行的端口打开(任意选择一种方式即可)
-
方法1. 关闭防火墙 (CentOS中)
#直接关闭防火墙 [root@localhost bin]# systemctl stop firewalld
-
方法2. 打开Redis服务端口,假如我Redis的端口是6379
[root@localhost redisconf]# firewall-cmd --zone=public --add-port=6379/tcp --permanent success #重新加载 [root@localhost redisconf]# firewall-cmd --reload success #查看所有开放的端口 [root@localhost redisconf]# firewall-cmd --permanent --zone=public --list-ports 6379/tcp #读取配置文件启动Redis服务 [root@localhost bin]# /redis-server redisconf/redis.conf
-
-
需要关闭Redis的保护模式,如果开启了该模式,则只有本机能连接该Redis,其他外部的IP是无法连接的,在redis.conf中修改
-
如果Redis是在远程或者在linux虚拟机中,需要先启动Redis服务,也就是执行
redis-server redis.conf
整合Redis
步骤:
- 添加Redis依赖
springboot已经将对Redis的操作已经封装成一个类了,我们需要在springboot引入一个Redis依赖,该依赖中底层连接Redis的方法现在不是使用的 Jedis,而是使用的lettuce,因为lettuce是线程安全的,而Jedis是线程不安全的
<!--引入Redis的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在添加完这个依赖之后,spring Boot就会帮我们创建两个对象并放到了Spring容器中,叫做:RedisTemplate 和 StringRedisTemplate ,这两个对象就是我们在springboot中操作Redis需要使用的。
注意:RedisTemplate对象可以用来操作Redis中任意数据类型,比如String,List,Set,Zset,Hash等,而StringRedisTemplate只能操作String类型
- 在SpringBoot的配置文件application.yaml中配置Redis的连接信息,比如ip,启动端口号,密码,数据库等
#配置redis需要指定 host,ip,password
spring:
redis:
host: 192.168.226.128 #ip地址
port: 6381 #启动端口号,默认是6379端口
password: orange #Redis密码,也就是在redis.conf中requirepass中配置的
database: 0 #使用的Redis数据库的下标,默认是第一个,下标为0
-
测试连接Redis,使用redisTemplate 或 stringRedisTemplate对象来操作
– 对于redisTemplate对象中的方法:
解释:opsForSet :表示是对Redis中Set类型的操作 ,返回一个SetOperations对象,该对象中包括所有对Set类型的操作方法
opsForValue :表示是对Redis中String类型的操作 ,返回一个ValueOperations对象,该对象中包括所有对String类型的操作方法
opsForHash :表示是对Redis中Hash类型的操作 ,返回一个SetOperations对象,该对象中包括所有对Hash类型的操作方法
opsForZSet :表示是对Redis中ZSet类型的操作 ,返回一个SetOperations对象,该对象中包括所有对ZSet类型的操作方法
opsForList :表示是对Redis中List类型的操作 ,返回一个SetOperations对象,该对象中包括所有对List类型的操作方法
依此类推 …
除了这些还包括对Redis的简单操作
redisTemplate.keys("*") //查看所有的key redisTemplate.delete() //删除某些key redisTemplate.multi() //开启事务 redisTemplate.exec() //执行事务 redisTemplate.discard() //停止(中断)事务 ...
– 对于stringRedisTemplate对象中的方法 和 redisTemplate类似:
opsForValue :表示是对Redis中String类型的操作 ,返回一个ValueOperations**<String , String>**对象,该对象中包括所有对String类型的操作方法 ,同样还包括对Redis的简单操作
测试代码:
@SpringBootTest class SpringBootRedis05ApplicationTests { //直接将这两个对象注入,因为已经在spring容器中了,默认名字就是redisTemplate和stringRedisTemplate @Resource private RedisTemplate redisTemplate; @Resource private StringRedisTemplate stringRedisTemplate; @Test public void testRedis(){ //使用RedisTemplate添加一个String类型数据到Redis数据库 redisTemplate.opsForValue().set("testRedisTemplate","Hello,RedisTemplate"); //使用StringRedisTemplate添加一个String类型数据到Redis数据库 stringRedisTemplate.opsForValue().set("testStringRedisTemplate","Hello,StringRedisTemplate"); //分别获取添加的数据 System.out.println(redisTemplate.opsForValue().get("testRedisTemplate")); System.out.println(stringRedisTemplate.opsForValue().get("testRedisTemplate")); } }
输出结果:(连接成功,并且能正常存取值到Redis中)
在Redis中查看数据:
发现问题:使用RedisTemplate对象存入的数据键值对都是显示乱码的,而使用StrringRedisTemplate对象存入的数据键值对都是显示正常的
解释乱码原因
-
因为任何数据存入到Redis中都是需要先经过序列化的,然后将序列化之后的数据存入,之所以会造成RedisTemaplate对象数据显示乱码,而StringRedisTemaplate对象数据显示正常,根本原因:它们俩默认的 序列化方式不同
-
测试获取默认的序列化方式(包括对key和value的序列化方式)
@SpringBootTest
class SpringBootRedis05ApplicationTests {
@Resource
private RedisTemplate redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
public void testRedis(){
// redisTemplate.getConnectionFactory().getConnection().flushDb();
System.out.println("查看stringRedisTemplate的默认序列化方式");
System.out.println(stringRedisTemplate.getDefaultSerializer());
System.out.println(stringRedisTemplate.getKeySerializer());
System.out.println(stringRedisTemplate.getValueSerializer());
System.out.println("查看RedisTemplate的默认序列化方式");
System.out.println(redisTemplate.getDefaultSerializer());
System.out.println(redisTemplate.getKeySerializer());
System.out.println(redisTemplate.getValueSerializer());
}
}
输出结果:可以看出,这两个对象默认的序列化方式都是jdk的序列化,但是RedisTemplate对于key和value的序列化方式仍然使用jdk的序列化方式,而StringRedisTemplate对于key和value的序列化方式是字符串的序列化
jdk序列化:是将数据变成字节数组后传输,且jdk序列化是不支持跨平台和语言的,也就是先将key和value转换成字节数组后再存到Redis中的,所以显示的不是我们想看的。
解决办法
-
我们一般使用的序列化都是将key使用string的序列化,而value就是使用json的序列化,将value转换成一个json格式的字符串进行保存
-
如何修改默认RedisTemplate 的序列化配置?
源码分析:
在Redis的自动装配类RedisAutoConfiguration中创建了RedisTemplate对象,并注入到Spring容器的
@AutoConfiguration
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
//使用@Bean注解将方法返回值注入到spring容器,默认注入的是 RedisTemplate<Object, Object> 对象
@Bean
@ConditionalOnMissingBean(
name = {"redisTemplate"}
)
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
也就是说,如果存在一个bean叫做redisTemplate的时候,就不会调用这个方法,也就是该类不会再创建一个redisTemplate对象,所以我们可以自己创建一个叫做redisTemplate的对象,然后修改它的序列化方式,这样就使用我们自己创建的redisTemplate对象来进行对Redis的操作
总结一句话:创建自己的redisTemplate对象来覆盖springboot帮我们创建的,我们自己创建就可以指定序列化方式了
-
自己创建的配置类:
package com.example.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.RedisSerializer; import java.net.UnknownHostException; //加上@Configuration表示该类是一个配置类 @Configuration public class RedisConfig { //自己创建RedisTemplate对象并放到spring容器中去 @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { // 将redisTemplate 泛型设置为 <String, Object> RedisTemplate<String, Object> template = new RedisTemplate(); // 连接工厂,不必修改 template.setConnectionFactory(redisConnectionFactory); /* * 序列化设置 */ //redisTemplate 中的 key、hash的key 采用 String序列化方式 template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); //redisTemplate 中的 value、hash的value 采用 Jackson 序列化方式 template.setValueSerializer(RedisSerializer.json()); template.setHashValueSerializer(RedisSerializer.json()); template.afterPropertiesSet(); return template; } }
-
运行测试程序