在Java中操作Redis
1 介绍
前面我们讲解了Redis的常用命令,这些命令是我们操作Redis的基础,那么我们在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。
Redis 的 Java 客户端很多,官方推荐的有三种:
- Jedis
- Lettuce
- Redisson
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。
2 Jedis(理解)
1.Jedis使用介绍
Jedis 是 Redis 的 Java 版本的客户端实现。
maven坐标:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
使用 Jedis 操作 Redis 的步骤:
- 获取连接
- 执行操作
- 关闭连接
2. Jedis类常用方法
注:每个方法就是redis中的命令名,方法的参数就是命令的参数。
在每次访问Redis数据库的时候,都需要创建一个Jedis对象。每个Jedis对象似于JDBC中Connection对象,类似于mybatis中session对象。
连接和关闭 | 功能 |
---|---|
new Jedis(host, port) | 创建Jedis连接对象,参数: host: 服务器地址 port:端口号6379 |
void close() | 关闭连接 |
对string操作的方法 | 说明 |
---|---|
set(String key,String value) | 添加字符串类型的键和值 |
String get(String key) | 通过键得到字符串的值 |
del(String … keys) | 删除一个或多个键 |
对hash操作的方法 | 说明 |
---|---|
hset(String key,String field,String value) | 添加一个hash类型的键,字段和值 |
Map<String,String> hgetall(String key) | 通过一个键得到所有的字段和值,返回Map |
对list操作的方法 | 说明 |
---|---|
lpush(String key,String…values) | 从左边添加多个值到list中 |
List<String> lrange(String key,long start,long end) | 通过键得到指定范围的元素 |
对set操作的方法 | 说明 |
---|---|
sadd(String key,String…values) | 添加一个或多个元素 |
Set<String> smembers(String key) | 通过键得到集合所有的元素 |
对zset操作的方法 | 说明 |
---|---|
zadd(String key, double score, String member) | 添加一个键,分数和值 |
Set<String> zrange(String key, long start, long end) | 查询一个指定范围的元素 |
3、案例:Jedis的基本操作
目标
使用Jedis上面的方法来访问Redis,向服务器中写入字符串、hash和list类型,并且取出打印到控制台上。
操作步骤:
1.导入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
2.创建测试类,书写操作redis数据库的代码,代码一共分为三步:
【1】创建jedis对象,连接redis数据库服务器 new Jedis(host,port)
【2】 操作数据
【3】 关闭连接
【1.下面是操作字符串数据的代码】:
package com.itheima.sh.jedis_test_01;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.List;
public class JedisTest01 {
/*
jedis入门
*/
@Test
public void test01(){
//1.创建jedis对象,连接redis数据库服务器 new Jedis(host,port)
Jedis jedis = new Jedis("127.0.0.1",6379);
//2.操作数据
//【1】字符串
jedis.set("username", "柳岩");
//获取
String username = jedis.get("username");
System.out.println("username = " + username);
//一次性添加多个数据 mset(key1,value1,key2,value2,...)
jedis.mset("addr", "sh", "company", "黑马");
//获取所有的数据
List<String> values = jedis.mget("username", "addr", "company");
System.out.println("values = " + values);
//3.关闭连接
jedis.close();
}
}
控制台输出结果:
小结:
1.一次性添加多个字符串数据,使用的方法如下:
mset(key1,value1,key2,value2,...)
2.一次性获取所有的字符串:
List<String> mget(key1,key2,key3...);
【2.下面是操作hash数据的代码】:
package com.itheima.sh.jedis_test_01;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JedisTest01 {
/*
jedis入门
*/
@Test
public void test01(){
//1.创建jedis对象,连接redis数据库服务器 new Jedis(host,port)
Jedis jedis = new Jedis("127.0.0.1",6379);
//2.操作数据
//【2】hash
jedis.hset("person", "username", "锁哥");
//存储多个数据 注意这里map集合的键和值都是String类型
Map<String, String> map = new HashMap<>();
map.put("age", "18");
map.put("height", "180");
jedis.hmset("person", map);
//获取hash中的所有的数据
Map<String, String> map1 = jedis.hgetAll("person");
System.out.println(map1);
//3.关闭连接
jedis.close();
}
}
控制台输出结果:
小结:
1.向hash中添加一个数据:
jedis.hset(key, field, value);
2.向hash中添加多个数据:
jedis.hset(key, map集合);
3.获取hash中所有的数据:
Map<String, String> map1 = jedis.hgetAll(key);
4.3 Spring Data Redis(掌握)
4.3.1 介绍
Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。
网址:https://spring.io/projects/spring-data-redis
maven坐标:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.4.8</version>
</dependency>
Spring Boot提供了对应的Starter,maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Spring Data Redis中提供了一个高度封装的类:RedisTemplate,针对类似 Jedis 客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
- ValueOperations:简单K-V操作(String类型)
- SetOperations:set类型数据操作
- ZSetOperations:zset类型数据操作
- HashOperations:针对hash类型的数据操作
- ListOperations:针对list类型的数据操作
4.3.2 使用方式
4.3.2.1 环境搭建
直接导入素材中的代码到idea中即可:
第一步:创建maven项目springdataredis_demo,配置pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/>
</parent>
<groupId>com.itheima</groupId>
<artifactId>springdataredis_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.4.5</version>
</plugin>
</plugins>
</build>
</project>
第二步:编写启动类
package com.itheima;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
}
}
第三步:配置application.yml
spring:
#Redis相关配置
redis:
host: 192.168.200.128 # 连接linux系统的redis
port: 6379 # 端口号
database: 0 #操作的是0号数据库
解释说明:
spring.redis.database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。
可以通过修改Redis配置文件来指定数据库的数量。
第四步:提供测试类
package com.itheima.test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
public class SpringDataRedisTest {
@Autowired
private RedisTemplate redisTemplate;
}
4.3.2.2 操作字符串类型数据
需求:
1.存入数据和取出数据
2.存值并设置过期时间
3.如果存在值则不执行任何操作
/**
* 操作String类型的数据
*/
@Test
public void test01String(){
//获取操作String类型的接口对象
ValueOperations valueOperations = redisTemplate.opsForValue();
//存值
valueOperations.set("city123","beijing");
//取值
String value = (String) valueOperations.get("city123");
System.out.println(value);
//存值,同时设置过期时间 TimeUnit:超时时间单位
/*
void set(K key, V value, long timeout, TimeUnit unit);
key :字段key
value:key对应的值
timeout:超时时间
TimeUnit:超时时间单位
*/
valueOperations.set("username","suoge",10, TimeUnit.SECONDS);
//存值,如果存在则不执行任何操作
Boolean aBoolean = valueOperations.setIfAbsent("city1234", "nanjing");
System.out.println(aBoolean);
}
上述操作完毕之后,在客户端查看键,如下所示:
因为默认的key序列化器为JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别。如果我们想要存储的key是正常的key,我们可以使用如下配置类,当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象。
配置类:
package com.itheima.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.StringRedisSerializer;
/**
* Redis配置类
*/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/*
1.RedisConnectionFactory 是获取RedisConnection对象的,RedisConnection相当于jdbc中的连接对象Connection表示和
Redis进行连接
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
//创建Redis模板对象
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
//默认的Key序列化器为:JdkSerializationRedisSerializer
//StringRedisSerializer支持字符串类型的转化,而且默认使用UTF-8编码
//下面代码的意思是使用StringRedisSerializer序列化器替换默认的Key序列化器JdkSerializationRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
4.3.2.3 操作哈希类型数据
需求:
1.存储几个哈希类型的数据
2.获取哈希类型的数据
3.根据键获取哈希类型中的所有字段
4.获得hash结构中的所有值
/**
* 操作Hash类型数据
*/
@Test
public void testHash(){
//获取操作Hash类型的接口对象
HashOperations hashOperations = redisTemplate.opsForHash();
//存值 下面的代码相当于命令:hset person name xiaoming
//pseron表示键,name表示字段名 xiaoming表示字段值
hashOperations.put("person","name","xiaoming");
hashOperations.put("person","age","20");
hashOperations.put("person","address","bj");
//取值
//下面的代码相当于执行命令:hget 键 字段===》hget person age===>表示根据键和字段名获取字段值
String age = (String) hashOperations.get("person", "age");
System.out.println(age);
//获得hash结构中的所有字段
//下面的代码相当于执行命令:HKEYS 键===》HKEYS person
Set keys = hashOperations.keys("person");
for (Object key : keys) {
System.out.println(key);
}
//获得hash结构中的所有值
//HVALS 键
List values = hashOperations.values("person");
for (Object value : values) {
System.out.println(value);
}
}
4.3.2.4 操作列表类型数据
需求:
1.向列表中添加数据
2.查询列表中所有数据
/**
* 操作List类型的数据
*/
@Test
public void testList(){
//获取操作列表类型的接口对象
ListOperations listOperations = redisTemplate.opsForList();
//存值
//命令lpush 键 元素 元素...
listOperations.leftPush("mylist","a");
listOperations.leftPushAll("mylist","b","c","d");
//取值
//命令:lrange 键 开始 结束
//下面的代码是查询所有
List<String> mylist = listOperations.range("mylist", 0, -1);
for (String value : mylist) {
System.out.println(value);
}
//获得列表长度 命令:llen 键
Long size = listOperations.size("mylist");
for (int i = 0; i < size; i++) {
//出队列
//命令:rpop 键
//从右边删除一个元素,返回被删除的元素
String element = (String) listOperations.rightPop("mylist");
System.out.println(element);
}
}
4.3.2.5 操作set集合类型数据
需求:
1.向set集合中添加数据
2.获取指定set集合的所有的元素
3.删除指定set集合的数据
/**
* 操作Set类型的数据
*/
@Test
public void testSet(){
//获取操作set类型的接口对象
SetOperations setOperations = redisTemplate.opsForSet();
//存值
//sadd 键 元素 元素...
setOperations.add("myset","a","b","c","a");
//取值
//smembers 键 : 得到这个集合中所有的元素
Set<String> myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
//删除成员
//srem 键 元素 元素...
setOperations.remove("myset","a","b");
//取值
myset = setOperations.members("myset");
for (String o : myset) {
System.out.println(o);
}
}
4.3.2.6 操作有序集合类型数据
需求:
1.向zset中添加数据
2.从zset中取出数据
3.对某个值的分数进行加20
4.删除数据
/**
* 操作ZSet类型的数据
*/
@Test
public void testZset(){
//获取操作zSet类型的接口对象
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//存值
//Boolean add(K var1, V var2, double var3) var1 表示键 var2 表示值 var3表示分数
zSetOperations.add("myZset","a",10.0);//myZset 表示键 a 表示值 10.0 表示分数
zSetOperations.add("myZset","b",11.0);
zSetOperations.add("myZset","c",12.0);
zSetOperations.add("myZset","a",13.0);
//取值
//命令:zrange 键 开始索引 结束索引
//获取指定范围的元素,得到所有的元素,索引是0到-1
Set<String> myZset = zSetOperations.range("myZset", 0, -1);
for (String s : myZset) {
System.out.println(s);
}
//修改分数
//下面的方法表示在原来分数上进行加20
zSetOperations.incrementScore("myZset","c",20.0);
//删除成员
zSetOperations.remove("myZset","a","b");
//取值
Set<ZSetOperations.TypedTuple> myZset = zSetOperations.rangeWithScores("myZset", 0, -1);
for (ZSetOperations.TypedTuple typedTuple : myZset) {
Double score = typedTuple.getScore();
Object value = typedTuple.getValue();
System.out.println(score+"---"+value);
}
}
4.3.2.7 通用操作
需求:
1.获取Redis中所有的key
2.判断某个key是否存在
3.删除指定key
4.获取指定key对应的value的数据类型
/**
* 通用操作,针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){
//获取Redis中所有的key
Set<String> keys = redisTemplate.keys("*");
for (String key : keys) {
System.out.println(key);
}
//判断某个key是否存在
Boolean itcast = redisTemplate.hasKey("itcast");
System.out.println(itcast);
//删除指定key
redisTemplate.delete("myZset");
//获取指定key对应的value的数据类型
DataType dataType = redisTemplate.type("myset");
System.out.println(dataType.name());
}
4.3.2.8 整合连接池(能够理解连接池参数即可)
关于redis连接池并没有什么效果,配置好之后会优化获取连接性能。
pom引入依赖:
<!-- redis创建连接池,默认不会创建连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
配置连接池:
# 配置redis环境
spring:
redis:
# 默认连接本地localhost,如果仅仅连接本地redis服务,则可不写
host: 192.168.200.128
# 默认端口是6379,则省略不写
port: 6379
# redis实例中分为16分片库,索引位从0~15,默认操纵的是0
database: 0
lettuce:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 8 # 连接池中的最大空闲连接
min-idle: 1 # 连接池中的最小空闲连接