1.Redis
1.1关于Redis
Redis是一款基于内存使用了类似K-V结构来实现缓存数据的NoSQL非关系型数据库。
提示:Redis本身也会做数据持久化处理。
1.2Redis的简单操作
当已经安装Redis,并确保环境变量可用后,可以在命令提示符窗口(CMD)或终端(IDEA的Terminal,或MacOS/Linux的命令窗口)中执行相关命令。
在终端下,可以通过redis-cli
登录Redis客户端:
redis-cli
在Redis客户端中,可以通过ping
检测Redis是否正常工作,将得到PONG
的反馈:
ping
在Redis客户端中,可以通过set
命令向Redis中存入或修改简单类型的数据:
set name jack
在Redis客户端中,可以通过get
命令从Redis中取出简单类型的数据:
get name
如果使用的Key并不存在,使用
get
命令时,得到的结果将是(nil)
,等效于Java中的null
在Redis客户端中,可以通过keys
命令检索Key:
keys *
keys a*
注意:默认情况下,Redis是单线程的,keys
命令会执行整个Redis的检索,所以,执行时间可能较长,可能导致阻塞!
1.3在Spring Boot项目中读写Redis
首先,需要添加spring-boot-starter-data-redis
依赖项:
<!-- Spring Data Redis:读写Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
以上依赖项默认会连接localhost:6379
,并且无用户名、无密码,所以,当你的Redis符合此配置,则不需要在application.properties
/ application.yml
中添加任何配置就可以直接编程。如果需要显式的配置,各配置项的属性名分别为:
spring.redis.host
spring.redis.port
spring.redis.username
spring.redis.password
在使用以上依赖项实现Redis编程时,需要使用到的工具类型为RedisTemplate
,调用此类的对象的方法,即可实现读写Redis中的数据。
在使用之前,应该先在配置类中使用@Bean
方法创建RedisTemplate
,并实现对RedisTemplate
的基础配置,则在项目的根包下创建config.RedisConfiguration
类:
package cn.tedu.csmall.product.config;
import lombok.extern.slf4j.Slf4j;
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.io.Serializable;
/**
* Redis的配置类
*
* @author java@tedu.cn
* @version 0.0.1
*/
@Slf4j
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Serializable> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> redisTemplate
= new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(RedisSerializer.json());
return redisTemplate;
}
}
1.4测试Redis存储数据
package cn.tedu.csmall.product;
import cn.tedu.csmall.product.pojo.entity.Brand;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
@SpringBootTest
public class RedisTemplateTests {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
// 使用Redis时,Key是自由命名的
// 建议Key(名称)是分多段的
// 例如“品牌列表”,应该由 brand 和 list 这2个单词组成
// 并且,多个单词之间推荐使用英文的冒号进行分隔,例如:brand:list
// 对于同一种类型的数据,Key的第1段应该是相同的
// 例如,id=6对应的品牌数据的Key应该中:brand:item:6
// keys brand*
@Test
void testValueOpsSet() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 向Redis中“存入” / “修改”数据
String key = "username";
String value = "admin";
ops.set(key, value);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, value);
}
@Test
void testValueOpsSetObject() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 向Redis中“存入” / “修改”数据
String key = "brand:item:1";
Brand brand = new Brand();
brand.setId(1L);
brand.setName("大白象");
brand.setEnable(1);
ops.set(key, brand);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, brand);
key = "brand:item:2";
brand = new Brand();
brand.setId(2L);
brand.setName("大白兔");
brand.setEnable(1);
ops.set(key, brand);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, brand);
key = "brand:item:3";
brand = new Brand();
brand.setId(3L);
brand.setName("大白熊");
brand.setEnable(1);
ops.set(key, brand);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, brand);
}
@Test
void testValueOpsSetX() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 向Redis中“存入” / “修改”数据
String key = "phone";
String value = "13800138001";
ops.set(key, value, 1, TimeUnit.MINUTES);
log.debug("已经向Redis中写入Key={}且Value={}的数据!", key, value);
}
@Test
void testListRightPush() {
List<Brand> brands = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
Brand brand = new Brand();
brand.setId(i + 0L);
brand.setName("测试品牌" + i);
brands.add(brand);
}
ListOperations<String, Serializable> ops = redisTemplate.opsForList();
String key = "brand:list";
for (Brand brand : brands) {
ops.rightPush(key, brand);
}
}
}
1.5测试Redis读取数据
package cn.tedu.csmall.product;
import cn.tedu.csmall.product.pojo.entity.Brand;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
@SpringBootTest
public class RedisTemplateTests {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
// 使用Redis时,Key是自由命名的
// 建议Key(名称)是分多段的
// 例如“品牌列表”,应该由 brand 和 list 这2个单词组成
// 并且,多个单词之间推荐使用英文的冒号进行分隔,例如:brand:list
// 对于同一种类型的数据,Key的第1段应该是相同的
// 例如,id=6对应的品牌数据的Key应该中:brand:item:6
// keys brand*
@Test
void testValueOpsGet() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 从Redis中读取数据
String key = "username";
Serializable value = ops.get(key);
log.debug("已经从Redis中读取Key={}的数据,Value={}", key, value);
}
@Test
void testValueOpsGetObject() {
// ValueOperations:用于实现string(Redis)的读写
ValueOperations<String, Serializable> ops = redisTemplate.opsForValue();
// 从Redis中读取数据
String key = "brand1";
Serializable value = ops.get(key);
log.debug("已经从Redis中读取Key={}的数据,Value={}", key, value);
log.debug("读取到的数据的类型是:{}", value.getClass().getName());
Brand brand = (Brand) value;
log.debug("执行类型转换成功:{}", brand);
}
@Test
void testKeys() {
Set<String> keys = redisTemplate.keys("brand*");
for (String key : keys) {
log.debug("{}", key);
}
}
@Test
void testListSize() {
// 获取列表数据的长度
ListOperations<String, Serializable> ops = redisTemplate.opsForList();
String key = "brands";
Long size = ops.size(key);
log.debug("在Redis中Key={}的列表数据的长度为:{}", key, size);
}
@Test
void testListRange() {
// 取出列表
// 在列表中的每个元素都有2个下标
// 正数的下标是从第1个元素以0作为下标,开始递增的编号
// 负数的下标是从最后一个元素以-1作为下标,开始递减的编号
ListOperations<String, Serializable> ops = redisTemplate.opsForList();
String key = "brands";
long start = 0L;
long end = -1L;
List<Serializable> list = ops.range(key, start, end);
for (Serializable serializable : list) {
log.debug("{}", serializable);
}
}
}
1.6测试Redis删除数据
package cn.tedu.csmall.product;
import cn.tedu.csmall.product.pojo.entity.Brand;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
@SpringBootTest
public class RedisTemplateTests {
@Autowired
RedisTemplate<String, Serializable> redisTemplate;
// 使用Redis时,Key是自由命名的
// 建议Key(名称)是分多段的
// 例如“品牌列表”,应该由 brand 和 list 这2个单词组成
// 并且,多个单词之间推荐使用英文的冒号进行分隔,例如:brand:list
// 对于同一种类型的数据,Key的第1段应该是相同的
// 例如,id=6对应的品牌数据的Key应该中:brand:item:6
// keys brand*
@Test
void testDelete() {
String key = "name";
Boolean result = redisTemplate.delete(key);
log.debug("在Redis中删除了Key={}的数据,结果为:{}", key, result);
}
}