1. Redis的Java客户端
Redis 的 Java 客户端很多,常用的几种:
- Jedis
- Lettuce
- Spring Data Redis
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。
这里重点学习Spring Data Redis。
2. Spring Data Redis使用方式
2.1 介绍
Spring Data Redis 是Spring的一部分,提供了在 Spring 应用中通过简单的配置就可以访问Redis服务,对Redis底层开发包进行了高度封装。在Spring项目中,可以使用Spring Data Redis来简化Redis 操作。
Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
- ValueOperations:string数据操作
- SetOperations:set类型数据操作
- ZSetOperations:zset类型数据操作
- HashOperations:hash类型的数据操作
- ListOperations:list类型的数据操作
2.2 环境搭建
2.2.1 导入依赖
1)新建项目:
直接在新建项目时可以将Spring Data Redis集成进来。
2)现有项目:
在pom.xml文件中添加如下maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.2.2 配置Redis数据源
在配置文件中配置自己的Redis服务端地址和密码等:
# Redis配置
spring:
data:
redis:
host: localhost # Redis服务端地址
port: 6379 # Redis服务端端口(默认:6379)
password: your_password # 服务端密码(没有可以不写该配置项)
database: 10 # 该项目选择第几个数据库(默认为0号数据库)
其中:password与database不是非必须的。
password:若忘记可以自行查看redis的配置文件(redis.conf)。
database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。
2.2.3 配置序列化器
当前配置不是必须的,因为Spring Boot框架会自动装配RedisTemplate对象,但是默认的key序列化器会导致我们存到Redis中后的数据和原始数据有差别,会显示出一些乱码,但并没有错,只是用不同的序列化器,为了又更好的兼容性,还是建议配置一下序列化器。
package com.dgxz99.configruation;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
// 字符串序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// JSON序列化器
// Jackson序列化的映射器配置
ObjectMapper mapper = new ObjectMapper();
// 添加Java 8时间支持模块
mapper.registerModule(new JavaTimeModule());
// 设定序列化策略:直接基于字段而不依赖于getter和setter
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
// 设定对象类型策略
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 配置忽略空字段
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 最后创建JSON序列化器
Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(mapper, Object.class);
// 设定序列化器
// 创建Redis模板对象
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
//设置redis的连接工厂对象
redisTemplate.setConnectionFactory(redisConnectionFactory);
// key和hashKey通常使用字符串序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value和hashValue通常使用JSON序列化方式
redisTemplate.setValueSerializer(jsonSerializer);
redisTemplate.setHashValueSerializer(jsonSerializer);
return redisTemplate;
}
}
注意:必须将该配置注入Spring容器中,才能生效。注入方式使用
Bean注解。
2.3 操作常见数据类型
这里主要是学习怎么使用,故就在Spring Boot中的test类中做示范,一般来说,通常是在Service层装配redisTemplate,然后进行操作。
2.3.1 字符串
/**
* 操作字符串数据类型
*/
@Test
public void testString(){
// 主要方法:set get setex
redisTemplate.opsForValue().set("name", "小明");
// 这里默认是返回一个Object类型对象,需要转换为对应类型,若指定键不存在返回null
// Object name = redisTemplate.opsForValue().get("name");
String name = (String) redisTemplate.opsForValue().get("name");
System.out.println(name);
// TimeUnit是一个Java自带的类,其中枚举了许多时间单位。
redisTemplate.opsForValue().set("gender","男",2, TimeUnit.MINUTES);
}
先查看一下Redis数据库里的情况,方便查看,这里直接使用数据库图形工具。
可以看到,name和gender的值都被保存到数据库里,控制台也输出了name的值,证明get方法获取成功。并且,gender键的右上角有TTL倒计时,等倒计时结束,该key就自动删除了。
然后再解释关于TimeUnit这个类:
TimeUnit是一个Java自带的类,其中枚举了许多时间单位,如下,在设定上时可以自己选择合适的:
前面提到了关于
redisTemplate配置是不必要的,但是建议配置,这里我们看看不配置会是怎么样的。直接注释掉
Bean注解,使配置不生效。
/** * 测试redisTemplate配置类的效果 */ @Test void testRedisTemplate() { redisTemplate.opsForValue().set("city", "重庆"); String city = (String) redisTemplate.opsForValue().get("city"); System.out.println(city); }
可以发现(忘记贴图了-_-||,可以自己尝试),Redis数据库中出现了一些乱码的问题,但是Idea控制台还是正常输出,并没有任何影响。数据库中产生乱码的原因就是Redis默认的序列化器和Java的序列化器不一致导致的,故还是建议进行配置。
2.3.2 列表
后面就不在示范案例,大家根据语法自行尝试。
// 左插入元素
redisTemplate.opsForList().leftPush(列表的键, 值);
// 右插入元素
redisTemplate.opsForList().rightPush(列表的键, 值);
// 获取指定列表中指定索引的元素值(从0开始)
redisTemplate.opsForList().index(列表的键, 指定索引);
// 设定列表中指定索引的元素值
redisTemplate.opsForList().set(列表的键, 指定索引1, 值);
// 移除指定列表中为指定值的元素并指定移除数量
redisTemplate.opsForList().remove(列表的键, 移除数量, 被移除值);
// 获取列表中指定索引范围的元素,其中0、1、2代表第一、第二、第三个元素;-1、-2、-3代表倒数第一、第二、第三个元素,以此类推
redisTemplate.opsForList().range(列表的键, 起始索引, 终止索引);
2.3.3 哈希
// 设定哈希表中指定字段的值,若该字段不存在则添加该字段和值,存在则修改其值
redisTemplate.opsForHash().put(哈希表的键, 字段, 值);
// 获取指定哈希表中指定字段的值
redisTemplate.opsForHash().get(哈希表的键, 字段);
// 判断某字段是否存在于指定哈希表中
redisTemplate.opsForHash().hasKey(哈希表的键, 待判断字段);
// 删除指定哈希表中指定字段及其值
redisTemplate.opsForHash().delete(哈希表的键, 待删除字段);
2.3.4 集合
// 加入值到集合
redisTemplate.opsForSet().add(集合的键, 值);
// 从集合中移除指定值
redisTemplate.opsForSet().remove(集合的键, 值);
// 判断值是否存在于指定集合内
redisTemplate.opsForSet().isMember(集合的键, 待判断值);
// 获取一个集合内的全部元素
redisTemplate.opsForSet().members(集合的键);
2.3.5 有序集合
// 向指定有序集合添加一个值,若该值已经存在于该有序集合,但是分数和有序集合中该值对应的分数不同,则会更新该值的分数
redisTemplate.opsForZSet().add(有序集合的键, 值, 值的分数);
// 移除有序集合中的指定值
redisTemplate.opsForZSet().remove(有序集合的键, 待移除值);
// 获取有序集合中指定索引范围的值,并按照其分数升序排列,索引0、1、2代表第一、第二、第三个元素;-1、-2、-3代表倒数第一、第二、第三个元素,以此类推
redisTemplate.opsForZSet().range(有序集合的键, 起始索引, 终止索引);
// 获取有序集合中指定索引范围的值,并按照其分数降序排列
redisTemplate.opsForZSet().reverseRange(有序集合的键, 起始索引, 终止索引);