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



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






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

2、测试短信发送

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


service-sms
- <dependencies>
-
- <dependency>
- <groupId>com.atguigugroupId>
- <artifactId>service-baseartifactId>
- <version>0.0.1-SNAPSHOTversion>
- dependency>
-
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
-
-
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- dependency>
-
-
- <dependency>
- <groupId>com.aliyungroupId>
- <artifactId>aliyun-java-sdk-coreartifactId>
- dependency>
-
- dependencies>
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: 你的短信模板签名
- "1.0" encoding="UTF-8"?>
- <configuration>
-
- <contextName>atguiguSrbcontextName>
-
-
- <property name="log.path" value="D:/project/test/srb_log/sms" />
-
-
-
-
-
-
-
- <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.logfile>
- <append>trueappend>
- <encoder>
- <pattern>${FILE_LOG_PATTERN}pattern>
- <charset>${ENCODING}charset>
- encoder>
- appender>
-
- <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
-
-
- <file>${log.path}/log-rolling.logfile>
- <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.logfileNamePattern>
-
- <maxHistory>15maxHistory>
-
- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <maxFileSize>1000KBmaxFileSize>
- timeBasedFileNamingAndTriggeringPolicy>
- rollingPolicy>
-
- appender>
-
-
-
-
-
-
-
-
- <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>
- @SpringBootApplication
- @ComponentScan({"com.atguigu.srb", "com.atguigu.common"})
- public class ServiceSmsApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ServiceSmsApplication.class, args);
- }
- }
创建常量读取工具类: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报告如下错误信息(不影响程序的编译和运行):

解决方案参考文档:
创建测试类 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);
- }
- }
接口:创建 SmsService
- public interface SmsService {
-
- void send(String mobile, String templateCode, Map
param) ; - }
实现:创建 SmsServiceImpl
- @Service
- @Slf4j
- public class SmsServiceImpl implements SmsService {
-
- @Override
- public void send(String mobile, String templateCode, Map
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
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);
- }
- }
- }
- @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
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("短信发送成功");
- }
- }
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", "55317332@qq.com"))
- .build();
- }
2、测试
测试正确发送
测试手机号码不正确
测试业务限流
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.bootgroupId>
- <artifactId>spring-boot-starter-data-redisartifactId>
- <version>2.1.3.RELEASEversion>
- dependency>
-
- <dependency>
- <groupId>redis.clientsgroupId>
- <artifactId>jedisartifactId>
- <version>2.9.1version>
- dependency>