一、Redis的Java客户端
前面我们讲解了Redis的常用命令,这些命令是我们操作Redis的基础,那么我们在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。
Redis 的 Java 客户端很多,常用的几种:
-
Jedis
-
Lettuce
-
Spring Data Redis
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。
我们重点学习Spring Data Redis。
1、Spring Data Redis
(1)、概述
Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。
网址:https://spring.io/projects/spring-data-redis
Spring Boot提供了对应的Starter,maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:
-
ValueOperations:string数据操作
-
SetOperations:set类型数据操作
-
ZSetOperations:zset类型数据操作
-
HashOperations:hash类型的数据操作
-
ListOperations:list类型的数据操作
(2)、环境搭建
在application.yml文件,配置redis连接,如下:
spring:
redis:
host: localhost
port: 6379
password: 123456
2、操作常见类型数据
当环境搭建好之后,springboot框架会自动装配RedisTemplate,我们就可以在任意的位置来使用这个对象
下面我们可以先使用单元测试,来测试一下常见的对redis的操作
在test下新建测试类,并集成springboot,如下:
package com.itheima.test;
import com.itheima.CacheDemoApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest(classes = CacheDemoApplication.class)
@RunWith(SpringRunner.class)
public class RedisTest {
@Autowired
private RedisTemplate<String,String> redisTemplate;
@Test
public void test(){
System.out.println(redisTemplate);
}
}
-
上述代码中直接注入了RedisTemplate,并且指定了泛型为String
-
如果不指定泛型也可以进行操作,但是存储对象的时候需要进行序列化
-
一般项目中存储对象都会先转换为json字符串,再进行存储,所以一般会选择使用泛型为String,避免大量的序列化操作
-
(1)、操作字符串数据类型
/**
* 操作字符串类型的数据
*/
@Test
public void testString(){
// set get setex setnx
redisTemplate.opsForValue().set("name","小明");
String name = redisTemplate.opsForValue().get("name");
System.out.println(name);
redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
redisTemplate.opsForValue().setIfAbsent("lock","1");
redisTemplate.opsForValue().setIfAbsent("lock","2");
}
(2)、操作哈希类型数据
/**
* 操作哈希类型的数据
*/
@Test
public void testHash(){
//hset hget hdel hkeys hvals
redisTemplate.opsForHash().put("heima","name","tom");
redisTemplate.opsForHash().put("heima","age","20");
String name = (String) redisTemplate.opsForHash().get("heima", "name");
System.out.println(name);
Set keys = redisTemplate.opsForHash().keys("heima");
System.out.println(keys);
List values = redisTemplate.opsForHash().values("heima");
System.out.println(values);
redisTemplate.opsForHash().delete("heima","age");
}
(3)、操作列表类型数据
/**
* 操作列表类型的数据
*/
@Test
public void testList(){
//lpush lrange rpop llen
redisTemplate.opsForList().leftPushAll("mylist","a","b","c");
redisTemplate.opsForList().leftPush("mylist","d");
List mylist = redisTemplate.opsForList().range("mylist", 0, -1);
System.out.println(mylist);
redisTemplate.opsForList().rightPop("mylist");
Long size = redisTemplate.opsForList().size("mylist");
System.out.println(size);
}
(4)、操作集合类型数据
/**
* 操作集合类型的数据
*/
@Test
public void testSet(){
//sadd smembers scard sinter sunion srem
redisTemplate.opsForSet().add("set1","a","b","c","d");
redisTemplate.opsForSet().add("set2","a","b","x","y");
Set members = redisTemplate.opsForSet().members("set1");
System.out.println(members);
Long size = redisTemplate.opsForSet().size("set1");
System.out.println(size);
Set intersect = redisTemplate.opsForSet().intersect("set1", "set2");
System.out.println(intersect);
Set union = redisTemplate.opsForSet().union("set1", "set2");
System.out.println(union);
redisTemplate.opsForSet().remove("set1","a","b");
}
(5)、操作有序集合类型数据
/**
* 操作有序集合类型的数据
*/
@Test
public void testZset(){
//zadd zrange zincrby zrem
redisTemplate.opsForZSet().add("zset1","a",10);
redisTemplate.opsForZSet().add("zset1","b",12);
redisTemplate.opsForZSet().add("zset1","c",9);
Set zset1 = redisTemplate.opsForZSet().range("zset1", 0, -1);
System.out.println(zset1);
redisTemplate.opsForZSet().incrementScore("zset1","c",10);
redisTemplate.opsForZSet().remove("zset1","a","b");
}
(6)、通用命令操作
/**
* 通用命令操作
*/
@Test
public void testCommon(){
//keys exists type del
Set keys = redisTemplate.keys("*");
System.out.println(keys);
Boolean name = redisTemplate.hasKey("name");
Boolean set1 = redisTemplate.hasKey("set1");
for (Object key : keys) {
DataType type = redisTemplate.type((String) key);
System.out.println(type.name());
}
redisTemplate.delete("mylist");
}
-
访问业务接口,先查询缓存中是否存在
-
如果缓存中存在,直接返回数据,进行响应
-
如果缓存中不存在,从数据库中读取数据同时存入到缓存中,进行响应
关于缓存的使用,我们可以在项目中集成Spring Data Redis来完成缓存的添加,不过一般企业中,我们更多的是使用统一管理缓存的框架来实现,主要原因是,耦合度更低,切换缓存的成本较低