当前位置:网站首页>21:第三章:开发通行证服务:4:进一步完善【发送短信,接口】;(在【发送短信,接口】中,调用阿里云短信服务和redis服务;一种设计思想:BaseController;)
21:第三章:开发通行证服务:4:进一步完善【发送短信,接口】;(在【发送短信,接口】中,调用阿里云短信服务和redis服务;一种设计思想:BaseController;)
2022-06-27 10:27:00 【小枯林】
说明:
(1)声明:
● 这个项目,前端自己就不部署了;;;自己就使用浏览器或者postman测试接口了;;;但是,对于每个接口,在前端页面上的表现,自己都会阐述清楚;;;同时,如果遇到一些“必须在前端页面上才能说清楚的事”,自己也都会阐述清楚来龙去脉;
● 最重要的是要理清思路;
● 由于阿里云短信服务,限制同一个手机号在一天内最多发送10条短信;;;所以,在已经确保阿里云短信服务已经调通的情况下,在开发阶段测试的时候,自己一般会把调用阿里云短信服务的那条语句给注释掉;(短信有限,且发且珍惜~~)
目录
1.在【19:第三章:开发通行证服务:2:在程序中,打通阿里云短信服务;】,我们在程序中打通了阿里云短信服务;
2.在【20:第三章:开发通行证服务:3:在程序中,打通redis服务器;】中,我们在程序中打通了redis服务器;
3.本篇博客,就是完善【imooc-news-dev-user】这个用户微服务中的,【发送短信,接口】getSMSCode();
一:完善【imooc-news-dev-user】(这个用户微服务中)的【发送短信,接口】getSMSCode();
1.首先,完善【发送短信,接口】的定义;(即完善这个接口,在【imooc-news-dev-api】接口工程中的定义)
2.然后,完善【imooc-news-dev-user】(这个用户微服务中)的【短信验证码接口getSMSCode()】的实现;
零:本篇博客的合理性解释;
1.在【19:第三章:开发通行证服务:2:在程序中,打通阿里云短信服务;】,我们在程序中打通了阿里云短信服务;
(1)首先,我们在【imooc-news-dev-common】通用工程中,编写一个【调用阿里云短信服务,发送短信】的工具类:SMSUtils;;;自然,其他需要使用阿里云短信服务的地方(比如【imooc-news-dev-user】这个用户微服务)就可以调用这个工具类;
(2)然后,在【imooc-news-dev-user】这个需要调用阿里云短信服务的用户微服务中,我们编写【发送短信,接口】,去调用SMSUtils工具类;
● 首先,在【imooc-news-dev-api】接口工程中,定义了一个【发送短信,接口】getSMSCode();
● 然后,在【imooc-news-dev-user】这个用户微服务中,去实现这个接口;
(3)当时主要目的是测试阿里云短信服务是否OK,所以这个接口写的很简单,并没有严格按照“前后端约定”去写;
2.在【20:第三章:开发通行证服务:3:在程序中,打通redis服务器;】中,我们在程序中打通了redis服务器;
(1)首先,我们在【imooc-news-dev-common】通用工程中,编写一个【操作redis】的工具类:RedisOperator;;;这个类中,我们自己编写了很多操作redis的方法;;;自然,其他需要redis服务的地方(比如【imooc-news-dev-user】这个用户微服务)就可以调用这个工具类;
(2)然后,在【imooc-news-dev-user】这个需要使用redis的用户微服务中,我们在配置文件中,配置redis服务器的url、用户名、密码等内容;
(3)然后,在【imooc-news-dev-user】这个需要使用redis的用户微服务中,我们在测试用的HelloController中,编写了一个接口,去实测redis是否OK;
(4)当时主要目的是测试我们的程序是否可以连上redis,所以我们在一个纯测试的接口中,测试了一下;
3.本篇博客,就是完善【imooc-news-dev-user】这个用户微服务中的,【发送短信,接口】getSMSCode();
让这个短信接口,完善在调用阿里云短信服务的逻辑,同时加入调用redis服务的逻辑;
一:完善【imooc-news-dev-user】(这个用户微服务中)的【发送短信,接口】getSMSCode();
1.首先,完善【发送短信,接口】的定义;(即完善这个接口,在【imooc-news-dev-api】接口工程中的定义)
package com.imooc.api.controller.user; import com.imooc.grace.result.GraceJSONResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletRequest; @Api(value = "用户注册登录",tags = {"用户注册登录的controller"}) @RequestMapping("passport") public interface PassportControllerApi { /** * 获取短信验证码 * @param mobile:调用这个接口的时候,需要传手机号; * @param request:我们这儿注入HttpServletRequest,通过其可以获取用户ip; * @return */ @ApiOperation(value = "获得短信验证码", notes = "获得短信验证码", httpMethod = "GET") //前端那边的请求接口已经是“getSMSCode”了,所以自己在写后端接口的url的时候,别瞎写; @GetMapping("/getSMSCode") public GraceJSONResult getSMSCode(@RequestParam("mobile") String mobile, HttpServletRequest request); }说明:
(1)修改内容说明;
(2)因为在实际中,前端请求这个接口的时候,其完整url是【/passport/getSMSCode?mobile=' + mobile】;
● 所以,这个接口需要设置url,以和前端保持一致;同时,我们也需要接收前端参数mobile;
● 声明:其实,自己并没有部署前端(主要是懒,怕麻烦);自己想把更多的精力投入在后端上面;;所以,自己在测试本机后端接口的时候,就在postman或者浏览器上测试了;;;;但是,对于每个接口,在前端页面上的表现,自己都会说清楚;;;而且,遇到一些“必须在前端页面上才能说清楚的事”,自己也都会阐述清楚来龙去脉;
● 然后,我们这儿为了达到【同一个用户,在60秒内,不能重复发送验证码】的目的;;;这儿,是通过ip地址来判定是否是同一用户的;;;所以,我们注入了HttpServletRequest这个方法参数;;
2.然后,完善【imooc-news-dev-user】(这个用户微服务中)的【短信验证码接口getSMSCode()】的实现;
package com.imooc.user.controller; import com.imooc.api.BaseController; import com.imooc.api.controller.user.PassportControllerApi; import com.imooc.grace.result.GraceJSONResult; import com.imooc.utils.IPUtil; import com.imooc.utils.SMSUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; @RestController public class PassportController extends BaseController implements PassportControllerApi { final static Logger logger = LoggerFactory.getLogger(PassportController.class); @Autowired private SMSUtils smsUtils;//注入,我们自己编写的,阿里云短信服务工具类; /** * 获取短信验证码 * @return */ @Override public GraceJSONResult getSMSCode(String mobile, HttpServletRequest request) { //根据用户ip,限制用户在60秒内,只能获得一次验证码; String userIp = IPUtil.getRequestIp(request);//调用工具类,根据当前请求,获得用户ip; redisOperator.setnx60s(MOBILE_SMSCODE + ":" + userIp, userIp);//向redis中存储当前用户请求的ip,但是过来60秒后,这个数据就会超时消失; String randomCode = (int) ((Math.random() * 9 + 1) * 100000) + "";//随机验证码,6位或4位都可以 smsUtils.sendSMS(mobile, randomCode); //把后端,生成的、原生的验证码,存在redis中;后面,用户在前端输入验证码时,可以拿来验证; redisOperator.set(MOBILE_SMSCODE + ":" + mobile, randomCode, 30 * 60); return GraceJSONResult.ok(); } }说明:
(1)修改内容说明;
(2)根据HttpServletRequest获取该请求的ip地址;
● IPUtil工具类:对于这个工具类中内容,暂时可以不去深究;同时,可以看到这个工具类我们并没有使用IoC管理,同时其中的方法,我们设为了static;(一个暂留的问题:对于一个工具类,什么时候建议使用IoC管理,什么时候建议不使用IoC管理???)
package com.imooc.utils; import javax.servlet.http.HttpServletRequest; /** * 用户获得用户ip的工具类 */ public class IPUtil { /** * 获取请求IP: * 用户的真实IP不能使用request.getRemoteAddr() * 这是因为可能会使用一些代理软件,这样ip获取就不准确了 * 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。 * @param request * @return */ public static String getRequestIp(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } }(3)一个设计思想:在【api】接口工程中,定义一个BaseController,在这个BaseController中,注入一些(其他处理具体业务的微服务中的Controller中,大概率会用到的)对象;;;然后,其他处理具体业务的微服务中的Controller,可以继承这个BaseController;;;这样依赖,这些处理具体业务的微服务中的Controller,要想使用某些对象时,就不用再重复注入了;
● 为什么BaseController不使用IoC容器管理起来?原因有两点:(1)如果BaseController使用IoC容器管理起来的话,我们需要在PassportController中注入BaseController,这样一搞反而不优雅了,还不如上面的继承的做法;;(2)子类继承父类的时候,创建子类对象,会创建父类对象???
(4)把用户的ip,存到redis中;(PS:好像听说redis中值的过期时间,有时不太准哎……,所以,这种解决方案,有待商榷……在自己实际开发中,这种利用redis过期时间来解决业务问题的方案,慎选!)
● 假设用户的ip是【192.147.43.3】,那么只要保证我们存放到redis中的key是【mobile_smscode:192.147.43.3】,即只要保证这个key是唯一且有ip信息就够了;;;;其value究竟是【192.147.43.3】还是【“aahldjfsjk”】都不重要;;;;;因为,只要redis中有key为【mobile_smscode:192.147.43.3】的这条数据,同一个用户如果在60内再次发起请求时,其向redis中存数据的时候,就会发现redis中已经有key为【mobile_smscode:192.147.43.3】的数据了,,,就判定是同一个用户想在60秒内重复调用,自然就会被拒绝;
(5)在后台,随机生成一个验证码;(这个很简单,没什么好说的)
(6)调用阿里云短信服务,去把我们在后台生成的验证码,以短信的形式发送给用户;
(7)然后,把我们生成的验证码存到redis中;(后面,用户在前端输入收到的验证码时,我们会把【用户在收到短信后,在前端页面输入的验证码】和【redis中存储的原生的验证码】进行比对)
二:效果;
(1)首先,全局install一下;
(2)然后,启动【user】的主启动类;
(3)然后,访问【user】的【"/getSMSCode"】接口;
边栏推荐
- Oracle连接MySQL报错IM002
- Win10快捷键整理
- Concepts of concurrency, parallelism, asynchronism, synchronization, multithreading and mutual exclusion
- 【TcaplusDB知识库】Tmonitor单机安装指引介绍(一)
- JS file upload and download
- Product strength benchmarking seal /model 3, with 179800 pre-sales of Chang'an dark blue sl03
- Border affects the height of the parent element - solution
- 【TcaplusDB知识库】Tmonitor后台一键安装介绍(一)
- Leetcode to do questions
- Evolution of software system architecture
猜你喜欢
![[200 opencv routines] 211 Draw vertical rectangle](/img/57/5ff4ccb6f003e1ec6c49de8c8fde16.png)
[200 opencv routines] 211 Draw vertical rectangle

ci/cd自动化测试_CI / CD管道加快测试自动化的16种最佳实践
Eureka核心源码解析

记一次 .NET 某物管后台服务 卡死分析

Working at home is more tiring than going to work at the company| Community essay solicitation

Comparison between new and old interfaces

红包雨: Redis 和 Lua 的奇妙邂逅

【HCIE-RS复习思维导图】- STP

Oracle连接MySQL报错IM002

oracle触发器 存储过程同时写入
随机推荐
Ubuntu手动安装MySQL
Quelles sont les fonctions de base nécessaires au développement d'applications de commerce électronique en direct? Quelles sont les perspectives d'avenir?
C语言学习-Day_06
通俗易懂理解樸素貝葉斯分類的拉普拉斯平滑
Comparison between new and old interfaces
【TcaplusDB知识库】Tmonitor后台一键安装介绍(一)
Use of bufferedwriter and BufferedReader
Go zero micro Service Practice Series (VII. How to optimize such a high demand)
When does the mobile phone video roll off?
Review of last week's hot spots (6.20-6.26)
Brother sucks 590000 fans with his unique "quantum speed reading" skill: look at the street view for 0.1 seconds, and "snap" can be accurately found on the world map
C language learning day_ 04
Queue, two-way queue, and its application
Experiment notes - Convert Carmen (.Log.Clf) file to rosbag
Win10 shortcut key sorting
12 necessary tools for network engineers
[cloud enjoys freshness] community weekly · vol.68- Huawei cloud recruits partners in the field of industrial intelligence to provide strong support + business realization
[tcapulusdb knowledge base] tcapulusdb machine initialization and launch introduction
Error im002 when Oracle connects to MySQL
torchvision. models._ utils. Intermediatelayergetter tutorial






















