阅读完需:约 10 分钟
使用 Java 操作 Redis 的方案很多,Jedis 是目前较为流行的一种方案,除了 Jedis ,还有很多其他解决方案。
除了这些方案之外,还有一个使用也相当多的方案,就是 Spring Data Redis。
在传统的 SSM 中,需要开发者自己来配置 Spring Data Redis ,这个配置比较繁琐,主要配置 3 个东西:连接池、连接器信息以及 key 和 value 的序列化方案。
在 Spring Boot 中,默认集成的 Redis 就是 Spring Data Redis,默认底层的连接池使用了 lettuce ,开发者可以自行修改为自己的熟悉的,例如 Jedis。
Spring Data Redis 针对 Redis 提供了非常方便的操作模板 RedisTemplate 。这是 Spring Data 擅长的事情,那么接下来我们就来看看 Spring Boot 中 Spring Data Redis 的具体用法。
在SpringBoot 2.4 之前没有要求但是在SpringBoot 2.5 后就有要求,想要远程连接Redis 需要一个依赖包(
SpringSecurity
),没有就连接不上!还有在Redis5.0之后想要开启远程连接 必须设置密码,不然开不了远程。
通过配置文件修改Redis的密码
在【redis.conf】配置文件中有一个【requirepass】配置项,这个配置项就是配置Redis访问密码的参数:
requirepass XXXXX(你的密码)
注意事项
1.修改访问密码之后要重启Redis。
2.设置的访问密码要尽可能复杂,尽可能长(正式上线)。因为Reids的查询速度是非常快的,如果一个不怀好意的外部用户想要破解密码的话,一秒钟可以尝试150K个密码,这时候只要设置的密码足够复杂足够长,就可以在一定程度上防止密码被轻易破解。
通过命令修改Redis的密码
修改Redis密码的命令是:
config set requirepass XXXXX(你的密码)
注意事项
1.通过命令修改访问密码不需要重启Redis(即时生效)。
2.如果【redis.conf】配置文件中的【requirepass】配置项已经被配置,通过命令修改的访问密码会被记录到该参数中,这种情况下修改之后是一直有效的。
3.如果【redis.conf】配置文件中的【requirepass】配置项没有被配置,通过命令修改的访问密码不会被记录到该参数中,这种情况下重启Redis之后密码就会失效。
查询Redis的密码与权限认证
查询Redis密码的命令是:
config get requirepass
不出意外的话,会报无操纵权限的错误:(error) ERR operation not permitted。
这时候需要先进行权限认证(检验密码):
auth XXXXX(你的密码)
进入正题:
Spring Data Redis
创建工程,引入 Redis 依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!--springBoot2.5以后必须要这个-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
配置 Redis 信息
接下来配置 Redis 的信息,信息包含两方面,一方面是 Redis 的基本信息,另一方面则是连接池信息:
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器连接密码
spring.redis.password=123
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器地址
spring.redis.host=192.168.66.128
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=5
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=10
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=1ms
# 连接超时时间(毫秒)
spring.redis.lettuce.shutdown-timeout=100ms
注意事项:
spring.redis.port=6379 有时候会报错提示: 6379地址已经在使用(6379是redis默认的端口) 这时候可以这样:
1.找到该进程;
找到redis-server 的进程 (Process Status)
输入命令:
ps -ef | grep -i redis
出现类似:
root 3086 1 0 Apr24 ? 00:00:07 ./bin/redis-server *:6379
root 3531 3467 0 01:00 pts/0 00:00:00 grep -i redis
进程号为 3086 即为redis服务器
2.杀死该进程;
使用kill 命令
输入命令:
kill -9 3086
3.然后重新启动redis服务器。
输入命令:
./redis-server
不过我没试过,因为我安装的是windows版的Redis。
因为我找不到windows里的这个进程(菜)所以就干脆改了spring.redis.port=6379为spring.redis.port=6377,换一个端口试试,还真的成功了!
不过游览器的地址也要换比如:http://localhost:6377/set
自动配置
当开发者在项目中引入了 Spring Data Redis ,并且配置了 Redis 的基本信息,此时,自动化配置就会生效。
我们从 Spring Boot 中 Redis 的自动化配置类中就可以看出端倪:
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
这个自动化配置类很好理解:
- 首先标记这个是一个配置类,同时该配置在 RedisOperations 存在的情况下才会生效(即项目中引入了 Spring Data Redis)
- 然后导入在 application.properties 中配置的属性
- 然后再导入连接池信息(如果存在的话)
- 最后,提供了两个 Bean ,
RedisTemplate
和StringRedisTemplate
,其中 StringRedisTemplate 是 RedisTemplate 的子类,两个的方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate
中的两个泛型都是 Object ,意味者存储的 key 和 value 都可以是一个对象,而StringRedisTemplate
的 两个泛型都是 String ,意味者 StringRedisTemplate 的 key 和 value 都只能是字符串。如果开发者没有提供相关的 Bean ,这两个配置就会生效,否则不会生效。
使用
接下来,可以直接在 Service (也可以直接在Controller里写用游览器直接打开) 中注入 StringRedisTemplate
或者 RedisTemplate
来使用:
Controller:
@RestController
public class HelloController {
@Autowired
StringRedisTemplate stringRedisTemplate=new StringRedisTemplate();
@GetMapping("/set")
public void set(){
ValueOperations<String,String> ops=stringRedisTemplate.opsForValue();
ops.set("name","java");
}
@GetMapping("/get")
public void get(){
ValueOperations<String,String> ops=stringRedisTemplate.opsForValue();
System.out.println(ops.get("name"));
}
}
回到正片 Service :
@Service
public class HelloService {
@Autowired
RedisTemplate redisTemplate;
public void hello() {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("k1", "v1");
Object k1 = ops.get("k1");
System.out.println(k1);
}
}
Redis 中的数据操作,大体上来说,可以分为两种:
- 针对 key 的操作,相关的方法就在 RedisTemplate 中
- 针对具体数据类型的操作,相关的方法需要首先获取对应的数据类型,获取相应数据类型的操作方法是 opsForXXX
调用该方法就可以将数据存储到 Redis 中去了,如下:

k1 前面的字符是由于使用了 RedisTemplate 导致的,RedisTemplate 对 key 进行序列化之后的结果。
RedisTemplate 中,key 默认的序列化方案是 JdkSerializationRedisSerializer
。
而在 StringRedisTemplate 中,key 默认的序列化方案是 StringRedisSerializer
,因此,如果使用 StringRedisTemplate
,默认情况下 key 前面不会有前缀。
不过开发者也可以自行修改 RedisTemplate 中的序列化方案,如下:
@Service
public class HelloService {
@Autowired
RedisTemplate redisTemplate;
public void hello() {
redisTemplate.setKeySerializer(new StringRedisSerializer());
ValueOperations ops = redisTemplate.opsForValue();
ops.set("k1", "v1");
Object k1 = ops.get("k1");
System.out.println(k1);
}
}
当然也可以直接使用 StringRedisTemplate
:
@Service
public class HelloService {
@Autowired
StringRedisTemplate stringRedisTemplate;
public void hello2() {
ValueOperations ops = stringRedisTemplate.opsForValue();
ops.set("k2", "v2");
Object k1 = ops.get("k2");
System.out.println(k1);
}
}
另外需要注意 ,Spring Boot 的自动化配置,只能配置单机的 Redis ,如果是 Redis 集群,则所有的东西都需要自己手动配置。
spring-data-redis针对jedis提供了如下功能:
1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类 2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口 ValueOperations:简单K-V操作 SetOperations:set类型数据操作 ZSetOperations:zset类型数据操作 HashOperations:针对map类型的数据操作 ListOperations:针对list类型的数据操作 3. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations: BoundValueOperations BoundSetOperations BoundListOperations BoundSetOperations BoundHashOperations 4. 将事务操作封装,有容器控制。 5. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer) JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。 StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。 JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】 OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】