Spring-Boot项目中集成阿里云短信服务
Spring Boot项目中集成阿里云短信服务
1. 导入阿里云依赖
首先,在你的
pom.xml
文件中添加阿里云短信服务的Maven依赖:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.24</version>
</dependency>
确保你已经包含了其他必要的依赖,如MySQL驱动和MyBatis:
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2. 配置客户端
2.1 在 application.properties
或 application.yml
中配置阿里云凭证
在
application.properties
中添加以下配置:
# 阿里云短信服务配置
sms.api-key=your-access-key-id
sms.secret=your-access-key-secret
或者在
application.yml
中:
sms:
api-key: your-access-key-id
secret: your-access-key-secret
2.2 创建配置类来初始化阿里云SDK客户端实例
创建一个配置类来初始化阿里云SDK的客户端实例:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AliyunSmsConfig {
@Value("${sms.api-key}")
private String accessKeyId;
@Value("${sms.secret}")
private String accessKeySecret;
@Bean
public IAcsClient acsClient() {
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
return new DefaultAcsClient(profile);
}
}
3. 发送短信
接下来,我们编写具体的业务逻辑来发送短信。
3.1 创建控制器来处理HTTP请求
创建一个控制器类来处理发送短信的请求:
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SmsController {
@Autowired
private IAcsClient acsClient;
@GetMapping("/sendSms/{phoneNumber}")
public String sendSms(@PathVariable("phoneNumber") String phoneNumber) {
CommonRequest request = new CommonRequest();
request.setSysMethod(com.aliyuncs.http.MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
// 设置参数
request.putQueryParameter("PhoneNumbers", phoneNumber);
request.putQueryParameter("SignName", "你的签名"); // 替换为已审核通过的签名名称
request.putQueryParameter("TemplateCode", "SMS_XXXXXX"); // 替换为你申请的模板Code
request.putQueryParameter("TemplateParam", "{\"code\":\"1234\"}"); // 根据模板内容设置参数
try {
CommonResponse response = acsClient.getCommonResponse(request);
return response.getData(); // 返回响应数据
} catch (ClientException e) {
e.printStackTrace();
return "Failed to send SMS.";
}
}
}
在这个示例中,我们定义了一个RESTful API端点
/sendSms/{phoneNumber}
,它接收手机号码作为路径变量,并尝试向该号码发送一条包含固定验证码(这里用
1234
代替)的短信。
3.2 使用异步方式发送短信(可选)
为了提高系统的并发处理能力,可以使用异步方式发送短信。首先启用异步支持:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
}
然后,在服务层中使用异步方法:
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SmsService {
@Autowired
private IAcsClient acsClient;
@Autowired
private SmsRecordMapper smsRecordMapper;
/**
* 异步发送短信的方法
*
* @param phoneNumber 接收短信的手机号码
* @param code 短信验证码
*/
@Async // 标记此方法为异步执行
public void sendSmsAsync(String phoneNumber, String code) throws ClientException {
CommonRequest request = new CommonRequest();
request.setSysMethod(com.aliyuncs.http.MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
// 设置参数
request.putQueryParameter("PhoneNumbers", phoneNumber);
request.putQueryParameter("SignName", "你的签名"); // 替换为已审核通过的签名名称
request.putQueryParameter("TemplateCode", "SMS_XXXXXX"); // 替换为你申请的模板Code
request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");
try {
CommonResponse response = acsClient.getCommonResponse(request);
// 记录发送结果
saveSmsRecord(phoneNumber, "验证码: " + code, response.getHttpStatus());
} catch (ClientException e) {
log.error("Failed to send SMS", e);
saveSmsRecord(phoneNumber, "验证码: " + code, -1); // 假设-1表示发送失败
}
}
/**
* 保存短信发送记录到数据库
*
* @param phoneNumber 手机号码
* @param message 短信内容
* @param status 发送状态(HTTP状态码或自定义错误码)
*/
public void saveSmsRecord(String phoneNumber, String message, Integer status) {
SmsRecord record = new SmsRecord();
record.setPhoneNumber(phoneNumber);
record.setMessage(message);
record.setStatus(status);
record.setSendTime(new Date());// 当前时间
smsRecordMapper.insert(record);
}
}
4. 签名和模板申请
4.1 签名申请
签名是短信内容前附加的个性化标识。你需要在阿里云控制台上申请签名,并等待审核通过。
示例代码:签名新增(Java)
创建服务接口和其实现类来处理签名申请:
import com.aliyuncs.dysmsapi.model.v20170525.AddSmsSignRequest;
import com.aliyuncs.dysmsapi.model.v20170525.AddSmsSignResponse;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public interface ISmsSignService {
AddSmsSignResponse createSmsSign(String signName, Integer signType, String remark, List<AddSmsSignRequest.SmsSignFileList> fileList) throws ClientException;
}
@Service
@Slf4j
public class SmsSignServiceImpl implements ISmsSignService {
@Autowired
private IAcsClient acsClient;
@Override
public AddSmsSignResponse createSmsSign(String signName, Integer signType, String remark, List<AddSmsSignRequest.SmsSignFileList> fileList) throws ClientException {
AddSmsSignRequest request = new AddSmsSignRequest()
.setSignName(signName)
.setSignSource(signType)
.setRemark(remark)
.setSmsSignFileList(fileList);
try {
return acsClient.getAcsResponse(request);
} catch (ClientException e) {
log.error("Failed to add SMS sign", e);
throw e;
}
}
}
4.2 模板申请
模板是具体要发送的短信内容格式。你需要在阿里云控制台上申请模板,并等待审核通过。
示例代码:模板新增(Java)
同样地,创建服务接口和其实现类来处理模板申请:
import com.aliyuncs.dysmsapi.model.v20170525.AddSmsTemplateRequest;
import com.aliyuncs.dysmsapi.model.v20170525.AddSmsTemplateResponse;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public interface ISmsTemplateService {
AddSmsTemplateResponse createSmsTemplate(String templateName, String templateContent, String remark) throws ClientException;
}
@Service
@Slf4j
public class SmsTemplateServiceImpl implements ISmsTemplateService {
@Autowired
private IAcsClient acsClient;
@Override
public AddSmsTemplateResponse createSmsTemplate(String templateName, String templateContent, String remark) throws ClientException {
AddSmsTemplateRequest request = new AddSmsTemplateRequest()
.setTemplateName(templateName)
.setTemplateContent(templateContent)
.setRemark(remark);
try {
return acsClient.getAcsResponse(request);
} catch (ClientException e) {
log.error("Failed to add SMS template", e);
throw e;
}
}
}
5. 数据库记录短信发送情况
5.1 配置数据源
在
application.properties
文件中配置MySQL数据源:
# MySQL DataSource Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis Configuration
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.yourproject.model
5.2 创建实体类和Mapper接口
假设我们需要存储短信发送记录,可以创建一个
SmsRecord
实体类和对应的Mapper接口。
import lombok.Data;
@Data
public class SmsRecord {
private Long id;
private String phoneNumber;
private String message;
private Date sendTime;
private Integer status;
}
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SmsRecordMapper {
@Insert("INSERT INTO sms_record(phone_number, message, send_time, status) VALUES(#{phoneNumber}, #{message}, NOW(), #{status})")
int insert(SmsRecord record);
}
对应的XML映射文件
SmsRecordMapper.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.yourproject.mapper.SmsRecordMapper">
<resultMap id="BaseResultMap" type="com.example.yourproject.model.SmsRecord">
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="phone_number" property="phoneNumber" jdbcType="VARCHAR"/>
<result column="message" property="message" jdbcType="VARCHAR"/>
<result column="send_time" property="sendTime" jdbcType="TIMESTAMP"/>
<result column="status" property="status" jdbcType="INTEGER"/>
</resultMap>
<insert id="insert" parameterType="com.example.yourproject.model.SmsRecord">
INSERT INTO sms_record(phone_number, message, send_time, status)
VALUES(#{phoneNumber}, #{message}, NOW(), #{status})
</insert>
</mapper>
6. 查询发送记录
为了确保短信成功发送或排查问题,你可以随时查询短信的发送状态。这通常也是通过调用API来完成的。
6.1 查询接口
调用查询接口获取特定时间段内的短信发送记录及其状态:
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class SmsQueryController {
@Autowired
private IAcsClient acsClient;
@GetMapping("/querySms/{phoneNumber}")
public String querySendStatus(@PathVariable("phoneNumber") String phoneNumber) {
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
request.setPhoneNumber(phoneNumber); // 设置目标手机号码
request.setSendDate(new SimpleDateFormat("yyyyMMdd").format(new Date())); // 设置查询日期
request.setPageSize(10L); // 设置每页大小
request.setCurrentPage(1L); // 设置当前页码
try {
QuerySendDetailsResponse response = acsClient.getAcsResponse(request);
return response.getBody().toString();
} catch (ClientException e) {
log.error("Failed to query SMS send status", e);
return "Failed to query SMS send status.";
}
}
}
总结
以上是对如何在Spring Boot项目中集成阿里云短信服务的详细说明。包括了依赖导入、配置客户端、发送短信的具体实现、签名和模板申请、数据库记录短信发送情况以及查询发送记录等关键步骤。请根据实际需求调整上述代码中的参数和配置项,例如替换真实的Access Key ID和Secret、签名名称和模板Code等。同时,确保敏感信息的安全管理,不要在公开场合暴露这些信息。