springBoot集成阿里云短信

news2024/12/28 20:12:12

第一步导入依赖

<dependencies>

    <dependency>
        <groupId>com.atguigu</groupId>
        <artifactId>service-base</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!--lombok用来简化实体类:需要安装lombok插件-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <!--阿里云短信-->
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>aliyun-java-sdk-core</artifactId>
    </dependency>

</dependencies>

第二部创建application.yml 配置文件
resources目录下创建文件
redis的目的是

erver:
  port: 8120 # 服务端口

spring:
  profiles:
    active: dev # 环境设置
  application:
    name: service-sms # 服务名

  #spring:
  redis:
    host: 192.168.100.100
    port: 6379
    database: 0
    password: 123456 #默认为空
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0

#阿里云短信
aliyun:
  sms:
    region-id: cn-hangzhou
    key-id: 你的keyid
    key-secret: 你的keysecret
    template-code: 你的短信模板code
    sign-name: 你的短信模板签名

第三步 从配置文件读取常量

@Setter
@Getter //idea2020.2.3版配置文件自动提示需要这个
@Component
//注意prefix要写到最后一个 "." 符号之前
//调用setter为成员赋值
@ConfigurationProperties(prefix = "aliyun.sms")
public class SmsProperties implements InitializingBean {

    private String regionId;
    private String keyId;
    private String keySecret;
    private String templateCode;
    private String signName;

    public static String REGION_Id;
    public static String KEY_ID;
    public static String KEY_SECRET;
    public static String TEMPLATE_CODE;
    public static String SIGN_NAME;

    //当私有成员被赋值后,此方法自动被调用,从而初始化常量
    @Override
    public void afterPropertiesSet() throws Exception {
        REGION_Id = regionId;
        KEY_ID = keyId;
        KEY_SECRET = keySecret;
        TEMPLATE_CODE = templateCode;
        SIGN_NAME = signName;
    }
}

Idea报告如下错误信息(不影响程序的编译和运行):
在这里插入图片描述

解决方案参考文档:
在这里插入图片描述
解决步骤:
step1:添加依赖

<!--  配置文件处理器  -->
<!--让自定义的配置在application.yaml进行自动提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

step2:启动processor
在这里插入图片描述
step3:重新编译模块
step4:这样就可以在yml文件中有自定义配置的提示信息啦
第四步配置启动类

@SpringBootApplication
public class ServiceSmsApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(ServiceSmsApplication.class, args);
    }
}

第五步测试工具类
创建测试类 UtilsTests,测试配置信息是否能正常获取

@SpringBootTest
@RunWith(SpringRunner.class)
public class UtilsTests {

    @Test
    public void testProperties(){
        System.out.println(SmsProperties.KEY_ID);
        System.out.println(SmsProperties.KEY_SECRET);
        System.out.println(SmsProperties.REGION_Id);
    }
}

第六步 短信发送业务

public interface SmsService {

    void send(String mobile, String templateCode, Map<String,Object> param);
}

实现:创建 SmsServiceImpl

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Override
    public void send(String mobile, String templateCode, Map<String,Object> param) {

        //创建远程连接客户端对象
        DefaultProfile profile = DefaultProfile.getProfile(
                SmsProperties.REGION_Id,
                SmsProperties.KEY_ID,
                SmsProperties.KEY_SECRET);
        IAcsClient client = new DefaultAcsClient(profile);

        //创建远程连接的请求参数
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", SmsProperties.REGION_Id);
        request.putQueryParameter("PhoneNumbers", mobile);
        request.putQueryParameter("SignName", SmsProperties.SIGN_NAME);
        request.putQueryParameter("TemplateCode", templateCode);

        Gson gson = new Gson();
        String json = gson.toJson(param);
        request.putQueryParameter("TemplateParam", json);

        try {
            //使用客户端对象携带请求对象发送请求并得到响应结果
            CommonResponse response = client.getCommonResponse(request);
            boolean success = response.getHttpResponse().isSuccess();
            //ALIYUN_RESPONSE_FAIL(-501, "阿里云响应失败"),
            Assert.isTrue(success, ResponseEnum.ALIYUN_RESPONSE_FAIL);

            String data = response.getData();
            HashMap<String, String> resultMap = gson.fromJson(data, HashMap.class);
            String code = resultMap.get("Code");
            String message = resultMap.get("Message");
            log.info("阿里云短信发送响应结果:");
            log.info("code:" + code);
            log.info("message:" + message);

            //ALIYUN_SMS_LIMIT_CONTROL_ERROR(-502, "短信发送过于频繁"),//业务限流
            Assert.notEquals("isv.BUSINESS_LIMIT_CONTROL", code, ResponseEnum.ALIYUN_SMS_LIMIT_CONTROL_ERROR);
            //ALIYUN_SMS_ERROR(-503, "短信发送失败"),//其他失败
            Assert.equals("OK", code, ResponseEnum.ALIYUN_SMS_ERROR);

        } catch (ServerException e) {
            log.error("阿里云短信发送SDK调用失败:");
            log.error("ErrorCode=" + e.getErrCode());
            log.error("ErrorMessage=" + e.getErrMsg());
            throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
        } catch (ClientException e) {
            log.error("阿里云短信发送SDK调用失败:");
            log.error("ErrorCode=" + e.getErrCode());
            log.error("ErrorMessage=" + e.getErrMsg());
            throw new BusinessException(ResponseEnum.ALIYUN_SMS_ERROR , e);
        }
    }
}

引入工具类
guigu-common中创建util包,引入工具类:
RandomUtils.java:生成四位或六位的验证码
RegexValidateUtils.java:常用正则表达式验证,这里提供了手机号码验证
创建controller
创建controller.api包,创建类ApiSmsController

@RestController
@RequestMapping("/api/sms")
@Api(tags = "短信管理")
@CrossOrigin //跨域
@Slf4j
public class ApiSmsController {

    @Resource
    private SmsService smsService;

    @Resource
    private RedisTemplate redisTemplate;

    @ApiOperation("获取验证码")
    @GetMapping("/send/{mobile}")
    public R send(
            @ApiParam(value = "手机号", required = true)
            @PathVariable String mobile){

        //MOBILE_NULL_ERROR(-202, "手机号不能为空"),
        Assert.notEmpty(mobile, ResponseEnum.MOBILE_NULL_ERROR);
        //MOBILE_ERROR(-203, "手机号不正确"),
        Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);

        //生成验证码
        String code = RandomUtils.getFourBitRandom();
        //组装短信模板参数
        Map<String,Object> param = new HashMap<>();
        param.put("code", code);
        //发送短信
        smsService.send(mobile, SmsProperties.TEMPLATE_CODE, param);

        //将验证码存入redis
        redisTemplate.opsForValue().set("srb:sms:code:" + mobile, code, 5, TimeUnit.MINUTES);

        return R.ok().message("短信发送成功");
    }
}

第七步 使用postman测试接口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【3】SCI易中期刊推荐——人工智能领域(中科院1区)

🚀🚀🚀NEW!!!SCI易中期刊推荐栏目来啦 ~ 📚🍀 SCI即《科学引文索引》(Science Citation Index, SCI),是1961年由美国科学信息研究所(Institute for Scientific Information, ISI)创办的文献检索工具,创始人是美国著名情报专家尤金加菲尔德(Eugene Garfield…

百货商场用户画像描绘与价值分析在线实习项目

通过实习可以让学生通过实践进行检验&#xff0c;它是衔接学生在校学习与步入社会两个阶段的重要桥梁。一个好的实习机会可以帮助学生积累工作经验&#xff0c;验证职业宣传同时提升综合素质。 在线实习项目重点是让学生巩固并拓展已学到的数据分析理论知识&#xff0c;对…

【无标题】测试开发 | TestNG 与 Junit 对比,测试框架如何选择?

TestNG 和 Junit 作为两大流行的测试框架&#xff0c;有哪些区别&#xff1f;各有哪些优缺点&#xff1f;该如何选择呢&#xff1f;这里简要总结下&#xff1a; 1. Junit 更适合隔离性比较强的单元测试&#xff1b; 2. TestNG 是比 Junit 涵盖功能更全面的测试框架&#xff0c…

【自学Java】Java for循环

Java for循环 Java for循环 在 Java 语言 中&#xff0c;关键字 for 用来操作已经知道了循环次数的循环操作&#xff0c;前面我们介绍过 while 和 do while 循环控制&#xff0c;他们一般情况下用于循环次数不知道的情况下。 Java for语句详解 语法 for(赋值初值 : 判断条…

第七章:使用Netlify零成本部署组件文档

第七章&#xff1a;使用Netlify无成本发布组件文档 为什么使用Netlify&#xff1f; 一开始一共有三个方案&#xff1a; 1、Github Page 2、Netlify 3、Vercel Github Page只支持一个repo发布一个网站&#xff0c;而我们的项目是一个mononrepo项目&#xff0c;后续可能还有其他…

数字转汉字支持负数和小数

private static String numToChinese(String str) {if(strnull)return null;boolean isPositivetrue;//判断是不是负数if(str.charAt(0)-)isPositivefalse;StringBuffer sbnew StringBuffer();if(!isPositive)sb.append("负");//整数部分和小数部分&#xff08;如果有…

2023年1月实时获取地图边界数据方法,省市区县多级联动【附区县乡镇街道geoJson文件下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

QT 学习笔记(十三)

文章目录一、QDataStream 二进制文件读写1. QDataStream 简介2. QDataStream 实际演示2.1 QDataStream 读写文件操作2.2 实现代码——主窗口头文件 widget.h2.3 实现代码——主窗口源文件 widget.cpp二、QTextStream 文本文件读写1. QTextStream 简介2. QTextStream 实际演示2.…

【王道操作系统】3.2.3 页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法)

页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法) 文章目录页面置换算法(最佳置换算法、先进先出置换算法、最近最久未使用置换算法、普通时钟置换算法、改造型时钟置换算法)1.最佳置换算法---OPT2.先进先出置换算…

[安洵杯 2019]不是文件上传(文件名不能用“,数据库可识别hex编码)

打开题目尝试上传文件发现只能上传图片&#xff0c;然后看见了图片的路径&#xff0c;但是图片码连不上蚁键&#xff0c;结合题目&#xff0c;然后看到了题目给出的github源码 <?php include("./helper.php"); $show new show(); if($_GET["delete_all&qu…

STS安装,SVN配置及WEB工程配置简单说明_1.0.0

Spring Tool Suite构建java web项目概述1, 下载安装Spring Tool Suite Spring Tool Suite 简称为sts, 为构建基于Spring企业应用&#xff0c;提供了最好的Eclipse开发环境。STS 提供了最新基于Java和Spring应用所需要的所有工具,STS官网主页地址为http://spring.io/tools/sts/,…

画布创作,签名大致就是起笔落笔

画布创作&#xff0c;签名大致就是起笔落笔 前言 在画布创作过程中&#xff0c;签名手的基本形态是&#xff0c;不停的点、划。 就像我们写字一样&#xff0c;字越写越大&#xff0c;但是我们不知道笔画的大小。 一个字是一个非常小的点、横&#xff0c;一个横就把这个字给分…

JVM学习(一):简单聊聊性能调优这门艺术

一、性能调优背景说明1.1 生产环境中的问题生产环境发生了内存溢出该如何处理&#xff1f;生产环境应该给服务器分配多少内存合适&#xff1f;如何对垃圾回收器的性能进行调优&#xff1f;生产环境CPU负载飙高该如何处理&#xff1f;生产环境应该给应用分配多少线程合适&#x…

2-2进程管理-处理机调度

文章目录一.调度的层次二.进程调度的时机、切换与过程、调度方式三.调度器、闲逛进程四.调度算法的评价指标五.调度算法&#xff08;一&#xff09;先来先服务SCFS&#xff08;二&#xff09;短作业优先算法SJF&#xff08;三&#xff09;高响应比优先HRRN&#xff08;四&#…

cas6.6关于redis连接问题的一次记录,主要问题 1远程主机强迫关闭了一个现有的连接,主要问题2ERR unknown command `HELLO`

项目背景&#xff1a; 公司要求用cas单点登录&#xff0c;这个cas需要引入redis当做ticket缓存&#xff0c;但是出现连接不上的问题由于用redismanager可视化软件看了是可以连接的&#xff0c;进行了查询是redis配置文件中需要配置参数问题截图如下 问题输出如下 2023-01-04…

192:vue+openlayers: 选择feature,弹窗操作,删除所选feature

第192个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中使用select来选择feature元素,选择的过程中弹窗出现删除和关闭按钮,删除的内容是selected的feature,关闭的是功能浮窗。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果Ope…

《设计模式》模板方法模式

《设计模式》模板方法模式定义&#xff1a; 模板方法模式又叫模板模式&#xff0c;在一个抽象类中公开定义了执行它的方法的模板&#xff0c;子类可以根据需要重写方法实现&#xff0c;但是调用将按照抽象类中定义的方式进行。模板方法模式相当于定义了一个操作中算法的骨架&a…

回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入多输出

回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入多输出 目录回归预测 | MATLAB实现CNN-GRU卷积门控循环单元多输入多输出预测效果基本介绍程序设计往期精彩参考资料预测效果 基本介绍 MATLAB实现CNN-GRU卷积门控循环单元多输入多输出&#xff0c;运行环境Matlab2020及以上…

【国科大模式识别】第三次作业

【题目一】现有四个来自于两个类别的二维空间中的样本, 其中第一类的两个样本为 (1,4)T(1,4)^T(1,4)T 和 (2,3)T(2,3)^T(2,3)T, 第二类的两个样本为 (4,1)T(4,1)^T(4,1)T 和 (3,2)T(3,2)^T(3,2)T 。这里, 上标 TTT 表示向量转置。若采用规范化增广样本表示形式, 并假设初始的权…

权限问题的理解——Linux

这里是目录标题一、重定向二、 学Linux的意义三、shell命令的运行原理四、Linux权限管理1.Linux中具体用户的分类五、Linux文件相关的权限概念文件类型文件的权限文件的权限操作去掉权限加上权限八进制文件权限操作更改文件的拥有者和所属组六、目录的权限七、默认权限权限掩码…