起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第29天,点击查看活动详情
前言
项目中经常会用到短信发送功能,例如用户登录需要发送验证码,通过验证码登录成功。本文将讲解Spring Boot如何发送短信,短信平台采用的阿里云平台为例。
环境准备
登录阿里云开通短信服务
- 登录阿里云在项目主页面,单击自有品牌App名称,进入自有品牌页面。
- 单击验证码短信服务对应的开通并授权服务。
- 在弹出的对话框中,点击授权服务
- 弹出的页面中点击同意授权即可
创建短信模板
按照要求选择模板类型、填写模板名称、模板内容、申请说明即可
集成短信
pom.xml文件中添加阿里云JAR包
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.0.3</version>
</dependency>
application.yml添加阿里云配置
config:
sms:
# 是否启用短信发送
enable: true
# 是否为测试短信
test: false
# 短信模板
template:
0: SMS_184220772
# 测试短信接收账号
test-recv-phone: 13612345678
accessKeyId: accessKeyId
regionId: regionId
secret: secret
request:
regionId: regionId
domain: domain
action: SendSms
version: 2017-05-25
signName: 自定义签名
短信配置类
@Component
@ConfigurationProperties(prefix="config.sms")
public class SmsConfig
{
private String regionId;
private String accessKeyId;
private String secret;
private Request request;
private boolean enable;
private boolean test;
private String testRecvPhone;
public static class Request
{
private String domain;
private String version;
private String action;
private String regionId;
private String signName;
}
// 省略get、set方法
}
短信核心实现类
public SmsResponse sendSms(SmsParameter smsParameter)
{
logger.info("sendSms param:",JSON.toJSONString(smsParameter));
String phones = smsParameter.getPhoneNumbers();
if(StringUtils.isEmpty(phones))
{
logger.warn("sendSms phone is empty");
throw new RuntimeException("短信发送失败,手机号码为空");
}
phones = phones.trim();
//添加阿里云相关的参数
DefaultProfile profile = DefaultProfile.getProfile(smsConfig.getRegionId(), smsConfig.getAccessKeyId(), smsConfig.getSecret());
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setMethod(MethodType.POST);
request.setDomain(smsConfig.getRequest().getDomain());
request.setVersion(smsConfig.getRequest().getVersion());
//
request.setAction(smsConfig.getRequest().getAction());
request.putQueryParameter("RegionId", smsConfig.getRequest().getRegionId());
// 如果是测试模式,那么发送给测试手机号
String phone = smsConfig.isTest() ? smsConfig.getTestRecvPhone() : smsParameter.getPhoneNumbers();
request.putQueryParameter("PhoneNumbers", phone);
//签名
request.putQueryParameter("SignName", smsParameter.getSignName());
//模板编号
request.putQueryParameter("TemplateCode", smsParameter.getTemplateCode());
//模板参数
request.putQueryParameter("TemplateParam", smsParameter.getTemplateParam());
logger.info("真实接收短信手机:{};是否发送短信:{}",phone,smsConfig.isEnable());
logger.trace("发送短信内容:{}",request);
// 启用了短信发送,才进行发送短信
if(smsConfig.isEnable())
{
try
{
CommonResponse response = client.getCommonResponse(request);
String result = response.getData();
logger.info("发送短信结果:{}",result);
// 尝试解析结果,根据结果判断是否发送成功
SmsResponse smsResponse= JSON.parseObject(result,SmsResponse.class);
return smsResponse;
}
catch (Exception e)
{
logger.error("send sms error",e);
throw new RuntimeException("短信发送失败",e);
}
}
else
{
logger.error("send sms config not enable");
}
return null;
}
说明:根据文档设置阿里云相关的参数即可。
短信测试
@RequestMapping("/sendSms")
public String sendSms()
{
//模板编号
String templateCode ="SMS_187640334";
//签名
String signName = smsConfig.getRequest().getSignName();
//发送电话号码
String phoneNumbers ="13612345678";
//随机生成验证码
int code=(int)(Math.random()*1000000);
String templateParam="{\"code\":\"" + code + "\"}";
SmsParameter smsParameter =new SmsParameter();
smsParameter.setTemplateCode(templateCode);
smsParameter.setTemplateParam(templateParam);
smsParameter.setPhoneNumbers(phoneNumbers);
smsParameter.setSignName(signName);
SmsResponse response =smsService.sendSms(smsParameter);
if("code".equals(response.getCode()))
{
return "发送短信成功";
}
else
{
return "发送短信失败";
}
}
注意
发送短信需要注意短信模板中的参数与其对应,且短信模板的参数采用的是键值对形式。测试采用的是短信验证码的模板只需要传入code值即可。
测试结果
[http-nio-9090-exec-1] INFO [] c.s.sms.service.SmsServiceImpl - 发送短信结果:{"RequestId":"4C95CC59-7632-521E-B559-FD3E5F9F7D5C","Message":"OK","BizId":"902804351291637542^0","Code":"OK"}
说明:发送短信成功的Code为OK说明短信发送成功。
其他特性
批量发送短信
发送短信参数的PhoneNumbers可以支持多个短信发送,使用逗号隔开,可以支持批量上线为1000个。
//批量发送
String phoneNumbers ="13612345678,1345678901";
短信并发控制,设置短信发送频率
方案1:阿里云配置短信发送发送频率
方案2:通过Redis限制发送的频率
关于Redis限制发送的频率的实现后续Redis的文章将详细讲解。
总结
本文讲解了Spring Boot发送短信,实际的项目中我们需要将短信和邮件进行统一封装成功独立服务,提供对应的API接口给其他服务调用即可。