当前位置: 首页 > news >正文

了解Redis的使用

目录

一、认识redis

1、redis的特点

1.1、redis的持久化

1.1.1、RDB(快照方式)

1.1.2、AOF(文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中

1.1.3、混合持久化:混合持久化结合了AOF和RDB持久化方式的优点

 2、redis中常见的数据结构

 2.1、String(字符串)常用命令

2.2、Hash(哈希)常用命令 

2.3、 List(列表)常用命令

2.4、Set(集合)常用命令

2.5、 Sorted Set(有序集合)常用命令

2.6、reidis中通用操作

3、 使用案例(短信验证码生成)


一、认识redis

redis是一个开源的基于内存的K-V存储的数据库,支持将数据持久化到磁盘,并且提供字符串(String),哈希(Hash),列表(Lists),集合(Sets),有序集合(Sorted Sets)等多种数据结构,使其不仅适用于简单缓存,还能高效处理复杂数据场景。由于redis的高性能,原子性操作,丰富的数据结构,持久化等特点,被广泛应用于缓存,会话存储,排行榜,消息队列等场景。

相比于关系型数据库(mysql),数据主要存储在磁盘上,采用表结构存储,支持sql查询和ACID事务,适合处理复杂查询和持久化数据存储,但在高并发读写场景下性能通常低于redis。redis使用于需要快速访问低延迟的业务,而mysql更适合强一致性、复杂关系查询的数据管理。两种数据库在实际应用中长结合使用,Redis作为缓存加速热点数据访问,MySQL作为持久化存储保证数据可靠性。

1、redis的特点

核心特点使用场景示例
基于内存存储高速缓存

电商网站缓存商品详情页,减少数据查询

社交平台缓存用户个人资料,提升访问速度

行文网站缓存热门文章,降低后端负载

丰富的数据结构多样化数据存储

例如String可以记录用户登录token

Hash可以存储对象数据,用户信息,商品属性

Set可以使用sinter计算交集做共同好友推荐

发布订阅模式实时消息系统聊天室消息广播,订单状态变更通知
单线程分布式锁

由于redis是单线程,所以天然就是线程安全,可以作为分布式锁

1.1、redis的持久化
1.1.1、RDB(快照方式)

通过快照的方式,将当前的redis内存当中的数据以二进制的格式保存到硬盘的一个文件中,快照文件是一个经过压缩的二进制文件。

优点:因为是一个二进制方式写入文件的,所以在数据恢复的时候,速度较快。并且快照文件是一个压缩文件,所以它占用磁盘空间小

缺点:这种持久化的方式缺点就是数据丢失,由于RDB是定期保存快照,所以在两次快照之间出现故障,可能会导致部分数据丢失。

1.1.2、AOF(文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中

AOF持久化是将Redis的写操作以日志的形式追加到一个文件中,类似于数据库的事务日志。当redis需要重启时,可以通过回访AOF文件中的写操作来恢复数据。

优点数据的完整性较好,因为是将写操作追加到文件中,所以他的数据完整性比RDB好,数据丢失的可能性低。可读性高,AOF是一个文本文件,用户可以方便的查看和分析其中的内容,也更容易进行手动修复。多种持久化策略,redis提供了不同的AOF持久化策略,可以根据需要选择不同级别的数据安全性和性能。

缺点文件较大,由于是追加写,AOF文件会随着时间增长,可能会变得比较打,较大的AOF文件可能会影响重启和恢复的速度。对磁盘的写入频繁,会对磁盘造成一定的写入压力。

1.1.3、混合持久化:混合持久化结合了AOF和RDB持久化方式的优点

混合持久化是redis4.0之后新增的方式,混合持久化是结合了RDB和AOF的优点,再写入的时候,先把当前的数据以RDB的形式写入文件的开头,在将后续的操作命令以AOF的格式存入文件,这样既能保证Redis重启时的速度,又能降低数据丢失的风险。

 2、redis中常见的数据结构

 2.1、String(字符串)常用命令
SET key value                   设置指定key的值
GET key                         获取指定key的值
SETEX key seconds value         设置指定key的值,并将key的过期时间设为seconds秒
SETNX key value                 只有key不存在时设置key的值

2.2、Hash(哈希)常用命令 

Hash是一个String类型的field和value的映射表,适用于存储对象

HSET key field value                  将哈希表key中的字段field的值设为value
HGET key field                        获取存储在哈希表中的指定字段的值
HDEL key field                        删除存储在哈希表中指定字段的值
HKEYS key                             获取哈希表中所有字段
HVALS key                             获取哈希表中所有值
HGETALL key                           获取在哈希表中指定key的所有字段和值

❗❗❗ 提示

1、Redis哈希特别适合存储多字段对象需要部分更新的场景,典型应用包括:

  • 用户、商品等结构化数据缓存
  • 动态配置管理
  • 轻量级统计计数
  • 替代简单关系型查询

2、注意事项

  • 大key问题:避免单个哈希存储过多字段,否则会影响性能。
  • TTL限制:哈希的过期时间只能对整个key设置(不能对单个field设置)
2.3、 List(列表)常用命令

list是简单的字符串列表,按照插入顺序排序,相当于链表的头插法。他是一个基于双向链表实现的数据结构,适用于轻量级的消息队列,实时数据流或者历史记录存储。

LPUSH key value1 [value2]          将一个或多个值插入到列表头部
LRANGE key start stop              获取一个或多个值插入到列表头部
LLEN key                           获取列表长度
BRPOP key1 [key2] timeout          移除并获取列表的最后一个元素,如果列表没有元素会阻塞列 表直到等待超时或发现可弹出元素为止

❗❗❗提示 

1️⃣LPUSH+BRPOP命令组合适用于异步任务处理,比如订单排队日志处理。生产者用LPUSH将任务插入列表头部,消费者用BROP从尾部阻塞获取任务,避免轮询。

2️⃣LPUSH+LRANGE命令组合适用于实时数据流,比如社交动态新闻推送

  • 如展示最新N条动态(如微信朋友圈,微博时间线)。
  • 用户发布动态时,LPUSH插入到列表头部,
  • 查询时用LRANGE0 9获取最新的10条数据。
2.4、Set(集合)常用命令

Set是String类型的无序集合,集合成员是唯一的,这意味着集合中不能出现重复的数据。常用于去重,并集和交集运算(如共同好友,标签系统)或快速成员检查(如黑名单)。

SADD key member1 [member2]                 向集合添加一个或多个成员
SMEMBERS  key                              返回集合中的所有成员
SCARD key                                  获取集合中的成员数
SINTER key1 [key2]                         返回给定所有集合的交集
SUNION key1 [key2]                         返回所有给定集合的并集
SDIFF key1 [key2]                          返回给定所有集合的差集
SREM key member1 [member2]                 移除集合中一个或多个成员

 ❗❗❗提示

1️⃣SADD+SMEMBERS组合可以用作去重存储,如用户标签,IP黑名单

  • 用SADD添加元素,自动去重。
  • 用SMEMBERS获取全部成员,如展示所有标签。

2️⃣SINTER取交集,可以用作获取共同好友

3️⃣SUNION取并集,可以用作获取共同兴趣

4️⃣SDIFF取差集,可以用作个性化推荐。比如推荐未浏览内容。

2.5、 Sorted Set(有序集合)常用命令

有序集合是String类型元素的集合,且不允许重复的成员。每个元素都会关联一个double类型的分数。Redis通过分数来未集合中的成员经行从大到小排序,有序集合的成员是唯一的,但分数却可以重复。在热榜排名中会用到。

ZADD key score1 member1 [score2 member2]   向有序集合添加一个或多个成员。
ZRANGE key start stop [WITHSCORES]         通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member               有序集合中对指定成员的分数加上增量increment
ZREM key member [member ...]               移除有序集合中的一个或多个成员

典型应用场景:如排行榜(游戏积分,热搜榜),延迟任务(用时间戳做分数,按到期时间排序),带权去重(如用户行为优先级去重)

2.6、reidis中通用操作
KEYS pattern           查找所有符合给定模式的key
EXISTS key             检查给定key是否存在
TYPE key               返回key锁存储的值的类型
TTL key                返回指定key剩余生存时间,以秒为单位
DEL key                该命令用于在key存在时删除key

3、 使用案例(短信验证码生成)

在springboot框架中通过Spring Data Redis模块提供了多种Redis数据结构的封装对象,方便开发者以面向对象的方式操作redis。

RedisTemplate是通用操作对象,他是最核心的Redis操作模板,支持所有Redis数据类型。常用的命令有

redisTemplate.opsForValue().set("key","value");  //String操作
redisTemplate.opsForList().leftPush("listKey","item"); //List操作
redisTemplate.opsForSet().add("setKey","a","b");  //set操作

当然我们操作String类型的时候,也可以使用StringRedisTemplate对象。

1️⃣springboot项目搭建完成之后,我们需要引入依赖,在pom文件当中完成。

<?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><groupId>org.example</groupId><artifactId>springboot-redis</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.0</version> <!-- 使用最新的稳定版本 --><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>3.1.5</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.9.3</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.9.3</version><scope>test</scope></dependency><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-launcher</artifactId><version>1.9.3</version><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.15</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.2.1</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.2.1</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-util</artifactId><version>9.3.7.v20160115</version></dependency>
<!--        生成验证码--><dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version></dependency></dependencies></project>

2️⃣配置application.yaml文件

spring:data:redis:host: 127.0.0.1port: 6379sms:host: https://wwsms.market.alicloudapi.compath: /send_smsmethod: POSTappcode: ddafe8cded8c436c8218cba7a8aac5b7templateId: wangweisms996

3️⃣从短信服务平台(比如阿里云的短信服务)复制手机短信发送的代码。MySmsUtil类

package org.example.utils;import lombok.Data;
import org.apache.http.HttpResponse;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;@Component
@ConfigurationProperties(prefix = "sms")
@Data
public class MySmsUtil {private String host;private String path;private String method;private String appcode;private String templateId;public String sendPhoneCode(String phone,String code) {Map<String, String> headers = new HashMap<String, String>();//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105headers.put("Authorization", "APPCODE " + appcode);//根据API的要求,定义相对应的Content-Typeheaders.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");Map<String, String> querys = new HashMap<String, String>();Map<String, String> bodys = new HashMap<String, String>();bodys.put("content", "code:"+code);bodys.put("template_id", templateId);   //注意,模板wangweisms996 仅作调试使用,下发短信不稳定,请联系客服报备自己的专属签名模板,以保障业务稳定使用bodys.put("phone_number", phone);//可以提交工单联系客服,或者钉钉联系,钉钉号:1ko_t720ssqc54try {/*** 重要提示如下:* HttpUtils请从\r\n\t    \t* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java\r\n\t    \t* 下载** 相应的依赖请参照* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml*/HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);System.out.println(response.toString());//获取response的body//System.out.println(EntityUtils.toString(response.getEntity()));return "给"+phone+"发送:"+code+" 成功";} catch (Exception e) {e.printStackTrace();return "给"+phone+"发送:"+code+"失败,原因:"+e.getMessage();}}}

4️⃣当然也要组成一个发送http请求的工具类HttpUtils

package org.example.utils;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;public class HttpUtils {/*** get* * @param host* @param path* @param method* @param headers* @param querys* @return* @throws Exception*/public static HttpResponse doGet(String host, String path, String method, Map<String, String> headers, Map<String, String> querys)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpGet request = new HttpGet(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}return httpClient.execute(request);}/*** post form* * @param host* @param path* @param method* @param headers* @param querys* @param bodys* @return* @throws Exception*/public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, Map<String, String> bodys)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpPost request = new HttpPost(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}if (bodys != null) {List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();for (String key : bodys.keySet()) {nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));}UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");request.setEntity(formEntity);}return httpClient.execute(request);}	/*** Post String* * @param host* @param path* @param method* @param headers* @param querys* @param body* @return* @throws Exception*/public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpPost request = new HttpPost(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}if (StringUtils.isNotBlank(body)) {request.setEntity(new StringEntity(body, "utf-8"));}return httpClient.execute(request);}/*** Post stream* * @param host* @param path* @param method* @param headers* @param querys* @param body* @return* @throws Exception*/public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpPost request = new HttpPost(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}if (body != null) {request.setEntity(new ByteArrayEntity(body));}return httpClient.execute(request);}/*** Put String* @param host* @param path* @param method* @param headers* @param querys* @param body* @return* @throws Exception*/public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpPut request = new HttpPut(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}if (StringUtils.isNotBlank(body)) {request.setEntity(new StringEntity(body, "utf-8"));}return httpClient.execute(request);}/*** Put stream* @param host* @param path* @param method* @param headers* @param querys* @param body* @return* @throws Exception*/public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpPut request = new HttpPut(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}if (body != null) {request.setEntity(new ByteArrayEntity(body));}return httpClient.execute(request);}/*** Delete*  * @param host* @param path* @param method* @param headers* @param querys* @return* @throws Exception*/public static HttpResponse doDelete(String host, String path, String method, Map<String, String> headers, Map<String, String> querys)throws Exception {    	HttpClient httpClient = wrapClient(host);HttpDelete request = new HttpDelete(buildUrl(host, path, querys));for (Map.Entry<String, String> e : headers.entrySet()) {request.addHeader(e.getKey(), e.getValue());}return httpClient.execute(request);}private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {StringBuilder sbUrl = new StringBuilder();sbUrl.append(host);if (!StringUtils.isBlank(path)) {sbUrl.append(path);}if (null != querys) {StringBuilder sbQuery = new StringBuilder();for (Map.Entry<String, String> query : querys.entrySet()) {if (0 < sbQuery.length()) {sbQuery.append("&");}if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {sbQuery.append(query.getValue());}if (!StringUtils.isBlank(query.getKey())) {sbQuery.append(query.getKey());if (!StringUtils.isBlank(query.getValue())) {sbQuery.append("=");sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));}        			}}if (0 < sbQuery.length()) {sbUrl.append("?").append(sbQuery);}}return sbUrl.toString();}private static HttpClient wrapClient(String host) {HttpClient httpClient = new DefaultHttpClient();if (host.startsWith("https://")) {sslClient(httpClient);}return httpClient;}private static void sslClient(HttpClient httpClient) {try {SSLContext ctx = SSLContext.getInstance("TLS");X509TrustManager tm = new X509TrustManager() {public X509Certificate[] getAcceptedIssuers() {return null;}public void checkClientTrusted(X509Certificate[] xcs, String str) {}public void checkServerTrusted(X509Certificate[] xcs, String str) {}};ctx.init(null, new TrustManager[] { tm }, null);SSLSocketFactory ssf = new SSLSocketFactory(ctx);ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm = httpClient.getConnectionManager();SchemeRegistry registry = ccm.getSchemeRegistry();registry.register(new Scheme("https", 443, ssf));} catch (KeyManagementException ex) {throw new RuntimeException(ex);} catch (NoSuchAlgorithmException ex) {throw new RuntimeException(ex);}}
}

5️⃣将生产验证码图片的代码放入到spring容器中。

package org.example.config;import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;@Configuration
public class KaptchaConfig {@Beanpublic DefaultKaptcha producer() {Properties properties = new Properties();properties.put("kaptcha.border", "no");properties.put("kaptcha.textproducer.font.color", "black");properties.put("kaptcha.textproducer.char.space", "5");properties.put("kaptcha.textproducer.char.length", "4");properties.put("kaptcha.image.height", "40");properties.put("kaptcha.image.width", "120");properties.put("kaptcha.textproducer.font.size", "30");Config config = new Config(properties);DefaultKaptcha defaultKaptcha = new DefaultKaptcha();defaultKaptcha.setConfig(config);return defaultKaptcha;}}

6️⃣注册和发送验证码Service层代码,当然这里在生成验证码的时候只需要文字部分,不需要生成图片。

package org.example.service.impl;import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.example.pojo.dto.UserDto;
import org.example.pojo.entry.User;
import org.example.pojo.resp.MyResponseResult;
import org.example.service.UserService;
import org.example.utils.MySmsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate DefaultKaptcha defaultKaptcha;@Autowiredprivate MySmsUtil mySmsUtil;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Overridepublic MyResponseResult<String> sendPhoneCode(String phone) {//1. 生成验证码String captchaText = defaultKaptcha.createText();//2. 发送短信String s = mySmsUtil.sendPhoneCode(phone, captchaText);//3. 将验证码存入到redis中stringRedisTemplate.opsForValue().set("tel_"+phone,captchaText,10, TimeUnit.MINUTES);//4. 返回结果return MyResponseResult.ok(s);}@Overridepublic MyResponseResult<String> register(UserDto userDto) {//获取phone和code数据String code = userDto.getCode();//与redis当中的数据进行比较String s = stringRedisTemplate.opsForValue().get("tel_"+userDto.getPhone());System.out.println(s);if(s == null || !code.equals(s)){return MyResponseResult.error(400,"验证码错误或过期",null);}stringRedisTemplate.delete("tel_"+userDto.getPhone());return MyResponseResult.ok("成功了");}
}

7️⃣、controller层代码

package org.example.controller;import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.example.pojo.dto.UserDto;
import org.example.pojo.resp.MyResponseResult;
import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/sendCode/{phone}")public MyResponseResult<String> phoneCode(@PathVariable String phone){//调用业务层,完成对手机号发送验证码,并且存入到redis当中进行验证用户的验证码是否正确return userService.sendPhoneCode(phone);}@PostMapping("/register")public MyResponseResult<String> register(@RequestBody UserDto userDto){return userService.register(userDto);}
}

8️⃣自定义返回类型

package org.example.pojo.resp;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MyResponseResult<T> {private Integer code;private String msg;private T data;public static <T> MyResponseResult<T> ok(T data){return MyResponseResult.<T>builder().code(200).data(data).msg("ok").build();}public static <T> MyResponseResult<T> ok(Integer code,String msg,T data){return MyResponseResult.<T>builder().code(code).data(data).msg(msg).build();}public static <T> MyResponseResult<T> error(T data){return MyResponseResult.<T>builder().code(400).data(data).msg("error").build();}public static <T> MyResponseResult<T> error(Integer code,String msg,T data){return MyResponseResult.<T>builder().code(code).data(data).msg(msg).build();}}

相关文章:

  • 如何给Hexo-butterfly主题博客在复制时添加版权声明
  • Hive SQL:一小时快速入门指南
  • 读取配置文件到Settings对象的完整实现
  • 【AS32系列MCU调试教程】驱动开发:AS32驱动库的集成与应用实例
  • 拓展:###单向循环链表###
  • comfyui插件和comfyui mac安装
  • 设备被看门狗重置问题
  • RHCE 练习四:编写脚本实现以下功能
  • web方向第一次考核内容
  • Linux免驱使用slcan,使用方法以Ubuntu为例
  • g++ a.cpp -o a ‘pkg-config --cflags --libs opencv4‘/usr/bin/ld: 找不到 没有那个文件或目录
  • [特殊字符] Next.js Turbo 模式不支持 @svgr/webpack 的原因与解决方案
  • Redis的list的底层原理
  • 后端通过nignx代理转发,提供接口供前端在防火墙外访问
  • Arduino入门教程​​​​​​​:4、打印字符到电脑
  • python中的模块化编程:日期模块、math算术模块、random模块
  • 国学IP行业实战洞察:聚焦创客匠人,解锁创始人IP与知识变现新路径
  • TDengine 如何从 2.x 迁移到 3.0
  • 用bilibili一个讲座视频,生成一本科普书籍
  • 苍穹外卖-day09
  • wordpress修改注册页面/网站关键词排名优化工具
  • 网站设计工作室/东莞建设网
  • wordpress名著/厦门seo排名扣费
  • 徐州网站开发/广东深圳疫情最新情况
  • 怎样做网站表白墙/产品推广渠道
  • 北京上地网站建设/谷歌商店paypal下载官网