👨🎓作者:bug菌
✏️博客:CSDN、掘金、infoQ、51CTO等
🎉简介:CSDN博客专家,C站历届博客之星Top50,掘金/InfoQ/51CTO等社区优质创作者,全网合计8w粉+,对一切技术感兴趣,重心偏Java方向;硬核公众号「 猿圈奇妙屋」,欢迎小伙伴们的加入,一起秃头,一起变强。
..
✍️温馨提醒:本文字数:1999字, 阅读完需:约 5 分钟
嗨,家人们,我是bug菌呀,我又来啦。今天我们来聊点什么咧,OK,接着为大家更《springboot零基础入门教学》系列文章吧。希望能帮助更多的初学者们快速入门!
小伙伴们在批阅文章的过程中如果觉得文章对您有一丝丝帮助,还请别吝啬您手里的赞呀,大胆的把文章点亮👍吧,您的点赞三连(收藏⭐+关注👨🎓+留言📃)就是对bug菌我创作道路上最好的鼓励与支持😘。时光不弃🏃🏻♀️,创作不停💕,加油☘️
一、前言🔥
环境说明:Windows10 + Idea2021.3.2 + Jdk1.8 + SpringBoot 2.3.1.RELEASE
经过前几期的由浅入深式的redis教学,想必你们也应该掌握的差不多了,现在我就来对这一块知识点进行一个大复盘,按照我的教学内容进度,我觉得你们应该要有如下能力,我先给大家一一罗列出来啊。
你们对应自身的学习情况,看看还有那一块内容是自己没有掌握的,尽快查缺补漏,凡是学习期间有任何疑问,欢迎下方留言或者加我的扣扣交流群,我会想尽办法帮助大家,让大家能把我这块知识点消化掉。好吧?
通过这几期教学内容,我觉得你们应该要掌握的能力有一下几点:
- 能独立完成springboot框架集成redis等相关配置。
- 能独立实现test-case并进行redis类方法实例测试。
- 能独立操作redis客户端玩转redis基本命令。
- 能独立实现redis相关业务代码。
- 能独立代码实现短信验证码场景等完整逻辑。
- ...
你们都对照下自己自身的学习情况,有任何不懂的及时提出来,不懂就问!好吧?
... ...
其实啊,我上边所教学的都是基于redis的数据类型之一字符串(String)。所以我不能够让大家"发育不良"啦。
接下来我再给大家重点介绍下redisd的其他几种数据类型吧。
二、redis常用数据类型
(1)String
这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。我上几期的内容教学,都是使用的String字符串。
我们再整体归纳一下,String型 redis命令操作:
-
set key value表示:设置key对应string类型的值。设置成功返回ok,失败则error。 -
setnx key value表示:如果key不存在,则设置key对应string类型的值。如果key已经存在,返回0 -
get key表示:获取指定key的值,如果key不存在,则返回nil,若key存在,则返回值。 -
getset key value表示:先获取key的值然后值覆盖,若key存在则返回旧值,若key不存在则返回nil。 -
mget key1key2 ... keyN表示:一次性获取多个key的值,如果对应key不存在,则对应位置返回nil。若存在,则对应返回对应的key的值。 -
mset key1value1 ... keyN表示:一次性设置多个key的值,如果对应key不存在,则返回ok,若存在,直接进行值覆盖。 -
...
(2)hash
这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。
我们再整体归纳一下,Hash型 redis命令操作:
-
hset keyfield value表示:设置hash field为指定值,如果key不存在,则创建。 -
hget keyfield表示:获取指定的hash field值。 -
hmget keyfiled1....fieldN表示:获取全部指定的hash filed。 -
hmset keyfiled1 value1 ...... filedN valueN表示:同时设置hash的多个field。 -
hincrbykey field integer表示: 将指定的hashfiled 加上指定值。成功返回hashfiled变更后的值。 -
hexistskey field表示:检测指定field是否存在。 -
hlen key表示:返回指定hash的field数量。 hkeys key 返回hash的所有field。 -
hvals key表示:返回hash的所有value。 -
hgetall表示:返回hash的所有filed和value。 -
...
(3)list
使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。
(4)set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
(5)sorted set
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
...
其实还有另外几种非常用的特殊数据类型,比如bitMap、Geospatial(地理位置)、HyperLogLog(基数统计).这个由于不是很常用,所以自行摸索哈。
... ...
接下来,是这几期redis教学的所有核心源码,我都一滴不剩的展示给的大家,就是希望大家能从我教的内容中真正学到东西,我也毫无保留的把我所学尽可能详细的阐述给大家听,毕竟都是这么过来的,对吧,我帮大家,我有不会的同时也希望大家不吝赐教哦。
三、附完整演示代码
1、PhoneCodeBuilder.java
如下是整个短信验证码场景实现代码:
package com.example.demo.component.redis.build;
import com.example.demo.component.redis.mediat.RedisMediator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 手机验证码组件
* * @author luoYong
* @version 1.0
* @date 2022/1/21 14:06
*/
@Component
public class PhoneCodeBuilder {
@Autowired
private RedisMediator redisMediator;
/**
* 随机获取六位数字
*
* @return
*/
public String getCode() {
int code = (int) ((Math.random() * 9 + 1) * 100000);
return String.valueOf(code);
}
/**
* 获取验证码,存入redis中并设置过期时间
*/
public void verifyCode(String phone) {
//1、定义手机号、验证码标识
String phoneKey = phone + "_count";
String codeKey = phone + "_code";
//2、每个号码只能发送三次
String count = redisMediator.get(phoneKey);
//3、从次数进行判断
if (count == null) {
//说明此号码第一次申请
//插入phone标识,并设置过期时间
redisMediator.set(phoneKey, "1", Long.valueOf(24 * 60 * 60));
} else if (Integer.parseInt(count) <= 2) {
//获取当前用户验证码剩余时间
long keyExpirationTime = redisMediator.getKeyExpirationTime(phoneKey);
System.out.println("keyExpirationTime:" + keyExpirationTime);
//获取当前次数
String codeCount = redisMediator.get(phoneKey);
//次数+1
int newCount = Integer.parseInt(codeCount) + 1;
redisMediator.set(phoneKey, String.valueOf(newCount), keyExpirationTime);
} else {
//当天3次机会用完了
System.out.println("当天3次机会用完了!请明日再试");
return;
}
//获取随机6位验证码
String code = this.getCode();
//验证码存入redis并设置过期时间(2min)
redisMediator.set(codeKey, code, Long.valueOf(2 * 60));
}
/**
* 校验验证码是否有效
*/
public boolean checkCode(String phone, String code) {
String codeKey = phone + "_code";
String redisCode = redisMediator.get(codeKey);
if (code.equals(redisCode)) {
return true;
}
return false;
}
2、RedisMediator.java
如下是封装的一些对redis进行操作的方法类。大家自行进行新增,需要就加在里头即可。
package com.example.demo.component.redis;
import com.example.demo.util.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* Redis中介类,用于从redis中读取内容或者更新数据
*
* @Author luoYong
* @Date 2022-01-20 17:47
*/
@Slf4j
@Component
public class RedisMediator {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Value("${luoyong.redis.login-time-out:1800}")
private Integer timeOut;
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
*/
public void set(String key, String value) {
set(key, value, timeOut);
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值 String
* @param time 过期时间
*/
public void set(String key, String value, long time) {
this.checkKey(key);
stringRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
}
/**
* 普通缓存获取
*
* @param key 键
*/
public String get(String key) {
this.checkKey(key);
return stringRedisTemplate.opsForValue().get(key);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
this.checkKey(key);
return stringRedisTemplate.hasKey(key);
}
/**
* 删除缓存
*
* @param key 健
*/
public void del(String key) {
this.checkKey(key);
stringRedisTemplate.delete(key);
}
/**
* 刷新缓存时间
*
* @param key
*/
public Boolean expire(String key) {
return this.expire(key, timeOut);
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public Boolean expire(String key, long time) {
return stringRedisTemplate.expire(key, time, TimeUnit.SECONDS);
}
/**
* 检查key是否为空
*
* @param key 健
*/
private void checkKey(String key) {
if (StringUtils.isBlank(key)) {
throw new RuntimeException("redis key不能为空");
}
}
/**
* 获取key的过期时间
*/
public long getKeyExpirationTime(String key){
this.checkKey(key);
return stringRedisTemplate.getExpire(key);
}}
3、PhoneCodeBuilderTest.java
如下是对手机号验证码功能的测试样例,大家可以参考一下:自己也可以封装自己想要测试的数据,这个随大家,开心就行。
package com.example.demo.component.redis.build;
import org.junit.jupiter.api.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;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PhoneCodeBuilderTest {
@Autowired
private PhoneCodeBuilder phoneCodeBuilder;
@Test
void testGetCode(){
String code = phoneCodeBuilder.getCode();
System.out.println(code);
}
@Test
void testVerifyCode(){
phoneCodeBuilder.verifyCode("10010");
}
}
4、RedisMediator.java
如下是对redis工具类的一些常用方法的测试用例,大家可以借鉴一下:同样,还有自己新增的一些工具类,大家也记得进行测试用例测试哦,别到时候拍上用场的时候,直接当场社死,毕竟没上过测试的代码,都不敢确保百分百一定没有问题,这点大家还是需要严谨一些。
package com.example.demo.component.redis.mediat;
import org.junit.jupiter.api.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;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RedisTest {
@Autowired
private RedisMediator redisMediator;
/**
* 插入一个key
*/
@Test
void testSetKey() {
redisMediator.set("name", "diaochan");
}
@Test
void testHasKey() {
boolean has = redisMediator.hasKey("name");
System.out.println("是否存在:" + has);
}
/**
* 获取一个key
*/
@Test
void testGetKey() {
String name = redisMediator.get("name");
System.out.println("获取到的name对于的值为:" + name);
}
/**
* 指定缓存失效时间(秒)
*/
@Test
void testExpireKey() {
redisMediator.expire("name", 3600);
}
/**
* 删除一个key
*/
@Test
void testDelKey() {
redisMediator.del("name");
}
}
好啦,redis的零基础入门,就止步于此啦!核心源码我都给大家了,大家可千万别辜负了bug菌的一片良苦用心啊。
俗话也说师傅带进门,修行靠个人,后边还有很多跟redis相关的知识点,像什么redis主从复制、redis的哨兵模式、redis的淘汰策略、redis持久化等等,这些都是日后需要大家自己慢慢摸索的,慢慢来吧,一起学习。谁都是从不会到会的,一点一滴积累,一定可以啃完吃透的哦,加油喔!我们都是最棒的。
... ...
OK,以上就是这期所有的内容啦,如果有任何问题欢迎评论区批评指正,咱们下期见。
四、往期热门推荐
- springboot系列(一):如何创建springboot项目及启动
- springboot系列(二):yaml、properties两配置文件介绍及使用
- springboot系列(三):多环境切换,实例演示
- springboot系列(四):stater入门
- springboot系列(五):史上最最最全springboot常用注解
- springboot系列(六):mysql配置及数据库查询
- springboot系列(七):如何通过mybatis-plus实现接口增删改查
- springboot系列(八):mybatis-plus之条件构造器使用手册
- springboot系列(九):mybatis-plus之如何自定义sql
- springboot系列(十):mybatis之xml映射文件>、<=等特殊符号写法
- springboot系列(十一):实现多数据源配置,开箱即用
- springboot系列(十二):如何实现邮件发送提醒,你一定得会(准备篇)
- springboot系列(十三):如何实现发送普通邮件?你一定得会
- springboot系列(十四):如何实现发送图片、doc文档等附件邮件?你一定得会
- springboot系列(十五):如何实现静态邮件模板发送?你一定得会
- springboot系列(十六):如何实现发送邮件提醒,附完整源码
- springboot系列(十七):集成在线接口文档Swagger2
- springboot系列(十八):如何Windows安装redis?你玩过么
- springboot系列(十九):如何集成redis?不会我教你
- springboot系列(二十):如何通过redis实现手机号验证码功能
- ... ...
文末🔥
如果还想要学习更多,小伙伴们可关注bug菌专门为大家创建的专栏《springboot零基础入门教学》,从无到有,从零到一!希望能帮助到更多小伙伴们。
我是bug菌,一名想走👣出大山改变命运的程序猿。接下来的路还很长,都等待着我们去突破、去挑战。来吧,小伙伴们,我们一起加油!未来皆可期,fighting!
感谢认真读完我博客的铁子萌,在这里呢送给大家一句话,不管你是在职还是在读,绝对终身受用。
时刻警醒自己:
抱怨没有用,一切靠自己;
想要过更好的生活,那就要逼着自己变的更强,生活加油!!!