首页 > 其他分享 >微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)

时间:2022-12-29 12:31:54浏览次数:42  
标签:code 短信 log 19 服务项目 ERROR 尚融宝 public String


认清现实,放弃幻想,准备斗争

阿里云短信服务

一、使用RAM子用户

1、进入子用户管理页面

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_微服务

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_微服务_02

2、添加用户 

3、获取子用户key

AccessKeyId, AccessKeySecret

这个玩意是找不回来的,创建的时候就应该马上保存下来,并且这玩意一般越久越不安全

4、设置用户权限

授权:AliyunDysmsFullAccess

二、开通短信服务

1、开通

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_java_03

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_阿里云_04

2、添加签名 

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_阿里云_05

 3、添加模板

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_云计算_06

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_阿里云_07

一般个人来说,很难申请到的,可以用他自带的玩意先弄,自带也有模板什么的 

4、套餐

free.aliyun.com

5、快速学习

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_java_08

三、测试短信发送

1、查找使用示例 

 2、测试短信发送

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_云计算_09

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_微服务_10

3、查看发送结果

短信服务->业务统计->发送记录查询

创建短信微服务

需求

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_微服务_11

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_云计算_12

一、创建项目

1、创建模块

service-sms

2、配置 pom.xml

<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>

3、application.yml

resources目录下创建文件

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: 你的短信模板签名

 4、logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<contextName>atguiguSrb</contextName>

<!-- 日志的输出目录 -->
<property name="log.path" value="D:/project/test/srb_log/sms" />

<!--控制台日志格式:彩色日志-->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) %highlight([%-5level]) %green(%logger) %msg%n"/>

<!--文件日志格式-->
<property name="FILE_LOG_PATTERN"
value="%date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n" />

<!--编码-->
<property name="ENCODING"
value="UTF-8" />

<!-- 控制台日志 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>

<!-- 文件日志 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${log.path}/log.log</file>
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>
</appender>

<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">

<!-- 要区别于其他的appender中的文件名字 -->
<file>${log.path}/log-rolling.log</file>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${ENCODING}</charset>
</encoder>


<!-- 设置滚动日志记录的滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-rolling-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<!--归档日志文件保留的最大数量-->
<maxHistory>15</maxHistory>

<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>1000KB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>

</appender>


<!-- <logger name="com.atguigu" level="INFO">-->
<!-- <appender-ref ref="CONSOLE" />-->
<!-- <appender-ref ref="FILE" />-->
<!-- </logger>-->

<!-- 开发环境和测试环境 -->
<springProfile name="dev,test">
<logger name="com.atguigu" level="INFO">
<appender-ref ref="CONSOLE" />
</logger>
</springProfile>

<!-- 生产环境 -->
<springProfile name="prod">
<logger name="com.atguigu" level="ERROR">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING_FILE" />
</logger>
</springProfile>
</configuration>

5、创建SpringBoot启动类

@SpringBootApplication
@ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
public class ServiceSmsApplication {

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

二、自定义配置

1、从配置文件读取常量

创建常量读取工具类:SmsProperties.java+

@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报告如下错误信息(不影响程序的编译和运行):

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_java_13

解决方案参考文档:


解决步骤:



step1:添加



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

step2:启动processor

微服务项目:尚融宝(19)(后端搭建:阿里云短信服务整合)_java_14


  • step3:重新编译模块
  • step4:这样就可以在yml文件中有自定义配置的提示信息啦

   2、测试工具类


创建测试类 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);
}
}


三、发送短信

1、短信发送业务

接口:创建 SmsService

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);
}
}
}

2、引入工具类


RegexValidateUtils.java:常用正则表达式验证,这里提供了手机号码验证


guigu-common中创建util包,引入工具类:
RandomUtils.java:生成四位或六位的验证码


 3、创建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("短信发送成功");
}
}

四、配置Swagger

1、添加配置

service-base中添加网站端api的配置

@Bean
public Docket apiConfig(){

return new Docket(DocumentationType.SWAGGER_2)
.groupName("api")
.apiInfo(apiInfo())
.select()
//只显示admin路径下的页面
.paths(Predicates.and(PathSelectors.regex("/api/.*")))
.build();

}

private ApiInfo apiInfo(){

return new ApiInfoBuilder()
.title("尚融宝-API文档")
.description("本文档描述了尚融宝接口")
.version("1.0")
.contact(new Contact("Helen", "http://atguigu.com", "[email protected]"))
.build();
}

2、测试

测试正确发送

测试手机号码不正确

测试业务限流


今日bug

2022-09-05 11:37:25 [ERROR] com.atguigu.common.exception.UnifiedExceptionHandler Unable to connect to Redis; nested exception is org.springframework.data.redis.connection.PoolException: Could not get a resource from the pool; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 192.168.231.137:6379

Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisTemplate' defined in class path resource [com/atguigu/srb/base/config/RedisConfig.class]: Unsatisfied dependency expressed through method 'redisTemplate' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {} 

 原因和解决

redis版本冲突出现问题,在base模块中引新的的依赖解决

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.1</version>
</dependency>

标签:code,短信,log,19,服务项目,ERROR,尚融宝,public,String
From: https://blog.51cto.com/u_15786786/5976693

相关文章

  • UVA193 Graph Coloring - 一般图最大独立集 -
    题目链接:https://www.luogu.com.cn/problem/UVA193题解:注意不是二分图最大独立集和最大匹配没啥关系直接dfs//bySkyRainWind#include<bits/stdc++.h>#definempr......
  • SQL Server 2019 内置函数
    SQLServer2019内置函数SQLServer为了日常方便加入了一些内置函数,可以供使用者直接使用,避免用户再去编写函数。如何学习过C语言可能知道,我们经常使用字符串处理函数,如......
  • Win 10 x64 Visual Studio 2019 编译 Detours 4.0.1
    Win10x64VisualStudio2019编译Detours4.0.1 十一年前,研究项目里用到的Detours已经更新到版本4.0.1,支持64位HOOK,从Github上下载下来编译看一下。GitHub下载......
  • vue中 WebSocket connection to 'ws://192.168.10.103:8080/ws' failed 问题的解决
    首先吧 vue中WebSocketconnectionto'ws://192.168.10.103:8080/ws'failed这个报错它不会影响你代码的运行,但是报错一定程度上影响页面的美观度。   下面我们......
  • 爱上 Mybatis源码 (2019-08-11)
     第一次学习源码,自己很难吃透源码,也做不到直接撸源码,一句一句的解析。先学习一下别人的文章,吃透源码的流程,日后有能力了再逐句撸。 源码的乐趣就在于首先能明白为什么我......
  • P5380 [THUPC2019]鸭棋
    题面查看题面题目背景鸭棋是一种风靡鸭子界的棋类游戏。事实上,它与中国象棋有一些相似之处,但规则不尽相同。在这里,我们将为你介绍鸭棋的规则。鸭棋在一个\(10\times......
  • 入门之路:“机器学习初学者”公众号2019年的精选原创文章
    “机器学习初学者”公众号2019年的精选原创文章合集,适合初学者入门AI。本文建议用微信收藏,用碎片时间学习。(黄海广)导语AI初学者最大的问题就是:资料太多!!!看不完!!!不知道如何......
  • 洛谷 P5363 / LOJ #3114 「SDOI2019」移动金币
    洛谷传送门LOJ传送门不错的博弈+计数。不难发现题中的游戏是阶梯Nim的变体。若设\(a_i\)为第\(i\)枚金币的位置,令\(\foralli\in[2,m],\b_i=a_i-a_{i-......
  • Leetcode 199
    199.BinaryTreeRightSideViewGiventherootofabinarytree,imagineyourselfstandingontherightsideofit,returnthevaluesofthenodesyoucansee......
  • 2019 中国.NET 开发者峰会正式启动
    ​​​​2014年微软组织并成立.NET基金会,微软在成为主要的开源参与者的道路上又前进了一步。2014年以来已经有众多知名公司加入.NET基金会,Google,微软,AWS三大云厂商已经齐聚.......