//本文作者:cuifuan
//本文将收录到菜单栏:《Spring全家桶》专栏中
首先,Redis是什么?
Redis是一个开源的,基于内存的键值数据存储,用作数据库,缓存和消息代理。在实现方面,Key-Value存储代表NoSQL空间中最大和最老的成员之一。Redis支持数据结构,如字符串,散列,列表,集和带范围查询的有序集。
在spring data redis的框架,可以很容易地编写,通过提供一个抽象的数据存储使用Redis的键值存储的Spring应用程序。 非关系型数据库,基于内存,存取数据的速度不是关系型数据库所能比拟的 redis是键值对(key-value)的数据库
有5中主要数据类型:
-
- 字符串类型 string
- 散列类型 hash
- 列表类型 list
- 集合类型 set
- 有序集合类型 zset
redis缓存为啥速度快
这么说吧,别人问你什么是“redis”,如果你知道,你可以直接吧啦吧啦一大堆,其实这个时候你的大脑就类似redis缓存,别人问的“redis”就是key,你说出来的结果就是value,而你如果不知道,你就去上网查,然后再告诉别人,这就类似于查询数据库了,你查了再告诉别人当然慢了!
你把脑袋里的东西写进笔记就类似redis持久化保存了;
你过了两个月把这玩意忘了,就是redis的定期删除了;
引自:https://blog.csdn.net/angleflyyy/article/details/81627785
准备工作
项目工具环境:-
- IDEA 2018.2
- Gradle 4+
- JDK1.8以上
- redis服务器
你把脑袋里的东西写进笔记就类似redis持久化保存了;
引自:https://blog.csdn.net/angleflyyy/article/details/81627785
设置Redis服务器
redis下载地址:https://redis.io/download
如果你的电脑是Mac:
1
brew install redis
brew install redis
然后运行redis服务器
12345678910111213141516171819202122232425
cuifuandeMacBook-Pro:~ cuifuan$ redis-server25336:C 29 Nov 2018 14:53:42.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo25336:C 29 Nov 2018 14:53:42.490 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=25336, just started25336:C 29 Nov 2018 14:53:42.490 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf25336:M 29 Nov 2018 14:53:42.491 * Increased maximum number of open files to 10032 (it was originally set to 256). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.2 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 25336 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 25336:M 29 Nov 2018 14:53:42.492 # Server initialized25336:M 29 Nov 2018 14:53:42.492 * Ready to accept connections
cuifuandeMacBook-Pro:~ cuifuan$ redis-server
25336:C 29 Nov 2018 14:53:42.490 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25336:C 29 Nov 2018 14:53:42.490 # Redis version=5.0.2, bits=64, commit=00000000, modified=0, pid=25336, just started
25336:C 29 Nov 2018 14:53:42.490 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
25336:M 29 Nov 2018 14:53:42.491 * Increased maximum number of open files to 10032 (it was originally set to 256).
.
.-``_ ‘’-._
.-``
.
. ‘’-._ Redis 5.0.2 (00000000/0) 64 bit
.-
.-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.
-.|’
_.-'| Port: 6379 |
-._
._ / _.-' | PID: 25336
-._
-._
-./ _.-‘ _.-‘
|`-.
-._
-..-‘ .-‘.-‘|
|
-._
-. .-‘.-‘ | http://redis.io
-._
-.
-.__.-'_.-' _.-' |
-.
-._
-._.-‘ .-‘.-‘|
|
-._
-. .-‘.-‘ |
-._
-.
-.__.-'_.-' _.-'
-.
-.__.-' _.-'
-. _.-‘
`-.__.-‘
25336:M 29 Nov 2018 14:53:42.492 # Server initialized
25336:M 29 Nov 2018 14:53:42.492 * Ready to accept connections
初始化项目
现在去Spring开始界面初始化一个项目
这里选择的是Gradle,选择完成点击Generate Projrct生成项目,这个时候会自动下载一个压缩包给你,解压过后导入,导入IDEA教程:http://note.youdao.com/noteshare?id=74e2d65e2d22cd684c3fdd6695b3ecdf
Gradle 依赖管理
让我们在build.gradle中为我们正在构建的示例应用程序声明必要的依赖项
12345678910111213141516171819202122232425262728293031
buildscript { repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RELEASE") }} apply plugin: 'java-library'apply plugin: 'org.springframework.boot'apply plugin: 'io.spring.dependency-management' group = 'com.example'version = '0.0.1-SNAPSHOT'sourceCompatibility = 1.8 repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }} dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'mysql:mysql-connector-java' implementation 'org.projectlombok:lombok' implementation 'org.apache.commons:commons-pool2:2.4.2' implementation 'com.alibaba:fastjson:1.2.51' testImplementation 'org.springframework.boot:spring-boot-starter-test'}
buildscript {
repositories {
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
}
dependencies {
classpath(“org.springframework.boot:spring-boot-gradle-plugin:2.1.0.RELEASE”)
}
}
apply plugin: ‘java-library’
apply plugin: ‘org.springframework.boot’
apply plugin: ‘io.spring.dependency-management’
group = ‘com.example’
version = ‘0.0.1-SNAPSHOT’
sourceCompatibility = 1.8
repositories {
maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/' }
}
dependencies {
implementation ‘org.springframework.boot:spring-boot-starter-data-jpa’
implementation ‘org.springframework.boot:spring-boot-starter-data-redis’
implementation ‘org.springframework.boot:spring-boot-starter-web’
implementation ‘mysql:mysql-connector-java’
implementation ‘org.projectlombok:lombok’
implementation ‘org.apache.commons:commons-pool2:2.4.2’
implementation ‘com.alibaba:fastjson:1.2.51’
testImplementation ‘org.springframework.boot:spring-boot-starter-test’
}
开始使用
凭借着SpringBoot的开箱即用的特点,集成Redis也不例外
- redisTemplate.opsForValue();//操作字符串
- redisTemplate.opsForHash();//操作hash
- redisTemplate.opsForList();//操作list
- redisTemplate.opsForSet();//操作set
- redisTemplate.opsForZSet();//操作有序set
在Spring的测试类中开始使用:
1
redisTemplate.opsForValue().set("username","test");
redisTemplate.opsForValue().set(“username”,”test”);
执行过后发现存在redis中的数据:
是乱的,是因为在set后redis会序列化key和value,所以我们要在config中重写一下redisTemplate
src/main/java/com/example/springbootredisdemo/config/RedisConfig.java
123456789101112131415161718192021222324252627282930313233
package com.example.springbootredisdemo.config; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericToStringSerializer;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer; @Configurationpublic class RedisConfig { private final RedisTemplate redisTemplate; @Autowired public RedisConfig(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } @Bean @SuppressWarnings("unchecked") public RedisTemplateString, Object redisTemplate() { RedisSerializerString stringSerializer = new StringRedisSerializer(); RedisSerializerObject jsonString = new GenericToStringSerializer(Object.class); redisTemplate.setKeySerializer(stringSerializer); redisTemplate.setValueSerializer(jsonString); redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setHashValueSerializer(jsonString); return redisTemplate; } }
package com.example.springbootredisdemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
private final RedisTemplate redisTemplate;
@Autowired
public RedisConfig(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Bean
@SuppressWarnings("unchecked")
public RedisTemplateString, Object redisTemplate() {
RedisSerializerString stringSerializer = new StringRedisSerializer();
RedisSerializerObject jsonString = new GenericToStringSerializer(Object.class);
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setValueSerializer(jsonString);
redisTemplate.setHashKeySerializer(stringSerializer);
redisTemplate.setHashValueSerializer(jsonString);
return redisTemplate;
}
}
再去执行一下刚刚的方法
经过自定义的序列化之后可以了,没有乱码了
opsForList()添加操作
123456789101112
@Test public void CsetListRedis(){ ListString trap = new ArrayList(); trap.add("张三"); trap.add("张无忌"); trap.add("新垣结衣"); //循环向userlist左添加值 trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value)); //向userlist右添加值 redisTemplate.opsForList().rightPush("userlist","rightValue"); log.info("userlist-{}",redisTemplate.opsForList().range("userlist",0,10)); }
@Test
public void CsetListRedis(){
ListString trap = new ArrayList();
trap.add(“张三”);
trap.add(“张无忌”);
trap.add(“新垣结衣”);
//循环向userlist左添加值
trap.forEach(value-redisTemplate.opsForList().leftPush(“userlist”,value));
//向userlist右添加值
redisTemplate.opsForList().rightPush(“userlist”,”rightValue”);
log.info(“userlist-{}”,redisTemplate.opsForList().range(“userlist”,0,10));
}
opsForList()删除操作
1234
@Test public void DlistRedisRemove(){ redisTemplate.opsForList().remove("userlist",0,"张无忌"); }
@Test
public void DlistRedisRemove(){
redisTemplate.opsForList().remove(“userlist”,0,”张无忌”);
}
通过源码看这里有三个参数:
opsForSet()添加操作
利用了set值的不可重复
12345678910111213
@Test public void CsetRedis(){ ListString trap = new ArrayList(); trap.add("张三"); trap.add("里斯"); trap.add("里斯"); trap.add("张无忌"); trap.add("新垣结衣"); System.out.print(trap.toString()); //循环向userlist左添加值 trap.forEach(value-redisTemplate.opsForSet().add("userSet",value)); log.info("取出userSet-{}",redisTemplate.opsForSet().members("userSet")); }
@Test
public void CsetRedis(){
ListString trap = new ArrayList();
trap.add(“张三”);
trap.add(“里斯”);
trap.add(“里斯”);
trap.add(“张无忌”);
trap.add(“新垣结衣”);
System.out.print(trap.toString());
//循环向userlist左添加值
trap.forEach(value-redisTemplate.opsForSet().add(“userSet”,value));
log.info(“取出userSet-{}”,redisTemplate.opsForSet().members(“userSet”));
}
结果
符合了Set集合的无序和不可重复性
opsForSet()的删除操作
这个删除操作就比较容易了,直接根据set的key值,后面参数写其需要删除的value就可以
1234
@Test public void EsetRedisRemove(){ redisTemplate.opsForSet().remove("userSet","张无忌"); }
@Test
public void EsetRedisRemove(){
redisTemplate.opsForSet().remove(“userSet”,”张无忌”);
}
opsForHash()操作
12345678910111213
//opsForHash()操作 @Test public void FhashRedisAdd(){ //添加 redisTemplate.opsForHash().put("user","phone",10086); redisTemplate.opsForHash().put("user","address","Shanghai"); redisTemplate.opsForHash().put("user","del","mubaba"); redisTemplate.opsForHash().put("user","dada","达达"); //修改 redisTemplate.opsForHash().put("user","address","Beijing"); //删除 redisTemplate.opsForHash().delete("user","del","dada"); }
//opsForHash()操作
@Test
public void FhashRedisAdd(){
//添加
redisTemplate.opsForHash().put(“user”,”phone”,10086);
redisTemplate.opsForHash().put(“user”,”address”,”Shanghai”);
redisTemplate.opsForHash().put(“user”,”del”,”mubaba”);
redisTemplate.opsForHash().put(“user”,”dada”,”达达”);
//修改
redisTemplate.opsForHash().put(“user”,”address”,”Beijing”);
//删除
redisTemplate.opsForHash().delete(“user”,”del”,”dada”);
}
结果
测试类SpringbootRedisDemoApplicationTests
src/test/java/com/example/springbootredisdemo/SpringbootRedisDemoApplicationTests.java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
package com.example.springbootredisdemo; import com.example.springbootredisdemo.service.NovelService;import lombok.extern.slf4j.Slf4j;import org.junit.FixMethodOrder;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.MethodSorters;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; import java.util.ArrayList;import java.util.List; //根据测试方法名字搞定执行顺序@FixMethodOrder(MethodSorters.NAME_ASCENDING)@RunWith(SpringRunner.class)@SpringBootTest@Slf4jpublic class SpringbootRedisDemoApplicationTests { @Autowired private NovelService novelService; @Autowired private RedisTemplateString,Object redisTemplate; private final static String KEY = "username"; private final static String VALUE = "test"; @Test public void AstringRedis(){ redisTemplate.opsForValue().set(KEY,VALUE); log.info("string set存储:{}-{}",KEY,VALUE); redisTemplate.opsForValue().get(KEY); log.info("string 根据{}取出{}",KEY,VALUE); } @Test public void BlistRedis(){ ListString trap = new ArrayList(); trap.add("张三"); trap.add("张三"); trap.add("张无忌"); trap.add("新垣结衣"); //循环向userlist左添加值 trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value));// redisTemplate.opsForList().leftPushAll("userlist",trap); //向userlist右添加值 redisTemplate.opsForList().rightPush("userlist","rightValue"); //取出userlist的值 log.info("userlist-{}",redisTemplate.opsForList().range("userlist",0,10)); } @Test public void CsetRedis(){ ListString trap = new ArrayList(); trap.add("张三"); trap.add("里斯"); trap.add("里斯"); trap.add("张无忌"); trap.add("新垣结衣"); System.out.print(trap.toString()); //循环向userlist左添加值 trap.forEach(value-redisTemplate.opsForSet().add("userSet",value)); log.info("取出userSet-{}",redisTemplate.opsForSet().members("userSet")); } @Test public void DlistRedisRemove(){ redisTemplate.opsForList().remove("userlist",0,"张无忌"); } @Test public void EsetRedisRemove(){ redisTemplate.opsForSet().remove("userSet","张无忌"); } //opsForHash()操作 @Test public void FhashRedisAdd(){ //添加 redisTemplate.opsForHash().put("user","phone",10086); redisTemplate.opsForHash().put("user","address","Shanghai"); redisTemplate.opsForHash().put("user","del","mubaba"); redisTemplate.opsForHash().put("user","dada","达达"); //修改 redisTemplate.opsForHash().put("user","address","Beijing"); //删除 redisTemplate.opsForHash().delete("user","del","dada"); }}
package com.example.springbootredisdemo;
import com.example.springbootredisdemo.service.NovelService;
import lombok.extern.slf4j.Slf4j;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
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;
import java.util.ArrayList;
import java.util.List;
//根据测试方法名字搞定执行顺序
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class SpringbootRedisDemoApplicationTests {
@Autowired
private NovelService novelService;
@Autowired
private RedisTemplateString,Object redisTemplate;
private final static String KEY = "username";
private final static String VALUE = "test";
@Test
public void AstringRedis(){
redisTemplate.opsForValue().set(KEY,VALUE);
log.info("string set存储:{}-{}",KEY,VALUE);
redisTemplate.opsForValue().get(KEY);
log.info("string 根据{}取出{}",KEY,VALUE);
}
@Test
public void BlistRedis(){
ListString trap = new ArrayList();
trap.add("张三");
trap.add("张三");
trap.add("张无忌");
trap.add("新垣结衣");
//循环向userlist左添加值
trap.forEach(value-redisTemplate.opsForList().leftPush("userlist",value));
// redisTemplate.opsForList().leftPushAll(“userlist”,trap);
//向userlist右添加值
redisTemplate.opsForList().rightPush(“userlist”,”rightValue”);
//取出userlist的值
log.info(“userlist-{}”,redisTemplate.opsForList().range(“userlist”,0,10));
}
@Test
public void CsetRedis(){
ListString trap = new ArrayList();
trap.add("张三");
trap.add("里斯");
trap.add("里斯");
trap.add("张无忌");
trap.add("新垣结衣");
System.out.print(trap.toString());
//循环向userlist左添加值
trap.forEach(value-redisTemplate.opsForSet().add("userSet",value));
log.info("取出userSet-{}",redisTemplate.opsForSet().members("userSet"));
}
@Test
public void DlistRedisRemove(){
redisTemplate.opsForList().remove("userlist",0,"张无忌");
}
@Test
public void EsetRedisRemove(){
redisTemplate.opsForSet().remove("userSet","张无忌");
}
//opsForHash()操作
@Test
public void FhashRedisAdd(){
//添加
redisTemplate.opsForHash().put("user","phone",10086);
redisTemplate.opsForHash().put("user","address","Shanghai");
redisTemplate.opsForHash().put("user","del","mubaba");
redisTemplate.opsForHash().put("user","dada","达达");
//修改
redisTemplate.opsForHash().put("user","address","Beijing");
//删除
redisTemplate.opsForHash().delete("user","del","dada");
}
}
小知识
方法名字前加ABCD…是为了让方法有执行顺序,根据测试方法名字搞定执行顺序,在方法上加注解 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
日志注解@Slf4j是为了让日志书写更方便
1234
//之前写日志 log.info("输出a"+index+"b"); //现在 log.info("输出a{}b",index);
//之前写日志
log.info(“输出a”+index+”b”);
//现在
log.info(“输出a{}b”,index);
多个参数可以用多个{},总之,喜欢哪个用哪个,谢谢!
码云代码地址
https://gitee.com/cuifuan/SpringBoot
点击图片加入Spring交流群
↓↓↓
看完本文有收获?请转发分享给更多人