SpringBoot整合阿里云短信服务实现方案

7 阅读3分钟

SpringBoot整合阿里云短信服务实现方案

一、阿里云短信服务准备工作

1. 开通阿里云短信服务

  1. 注册/登录阿里云账号(可使用支付宝/淘宝账号直接登录)
  2. 在阿里云首页搜索"短信服务"并进入控制台
  3. 点击"免费开通"按钮启用短信服务
  4. 如有需要,根据提示补充个人/公司资质信息

2. 获取必要的配置信息

  1. 短信签名(SignName):短信发送时显示的发送者名称,需在控制台申请
  2. 短信模板(TemplateCode):定义短信内容的固定部分和可替换参数,需在控制台申请
  3. AccessKey凭证:在阿里云控制台的"AccessKey管理"中创建和获取

二、SpringBoot项目整合

1. 添加Maven依赖

pom.xml文件中添加以下依赖:

<!-- 阿里云核心SDK -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.6.3</version>
</dependency>
<!-- 阿里云短信服务SDK -->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>2.2.1</version>
</dependency>
<!-- HTTP客户端 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

2. 配置文件设置

application.propertiesapplication.yml中添加配置:

application.properties方式:
# 阿里云访问凭证
spring.aliyun.access-key=your-access-key
spring.aliyun.secret-key=your-secret-key

# 阿里云短信服务配置
spring.aliyun.sms.sign-name=your-sign-name
spring.aliyun.sms.template-code=your-template-code
application.yml方式:
spring:
  aliyun:
    access-key: your-access-key
    secret-key: your-secret-key
    sms:
      sign-name: your-sign-name
      template-code: your-template-code

3. 编写短信服务实现类

创建AliyunSmsService.java

package com.example.service;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class AliyunSmsService {

    @Value("${spring.aliyun.access-key}")
    private String accessKey;
    
    @Value("${spring.aliyun.secret-key}")
    private String secretKey;
    
    @Value("${spring.aliyun.sms.sign-name}")
    private String signName;
    
    @Value("${spring.aliyun.sms.template-code}")
    private String templateCode;

    /**
     * 发送短信
     * @param phoneNumbers 手机号码
     * @param templateParam 短信模板参数
     * @return 发送结果
     */
    public boolean sendSms(String phoneNumbers, String templateParam) {
        // 手机号格式验证
        if (!validatePhone(phoneNumbers)) {
            return false;
        }
        
        try {
            // 初始化DefaultProfile
            DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKey, secretKey);
            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", "cn-hangzhou");
            request.putQueryParameter("PhoneNumbers", phoneNumbers);
            request.putQueryParameter("SignName", signName);
            request.putQueryParameter("TemplateCode", templateCode);
            request.putQueryParameter("TemplateParam", templateParam);

            // 发送请求
            CommonResponse response = client.getCommonResponse(request);
            
            // 解析响应结果
            String responseData = response.getData();
            return responseData.contains("\"Code\":\"OK\"");
        } catch (ClientException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 验证手机号格式
     * @param phone 手机号
     * @return 是否有效
     */
    private boolean validatePhone(String phone) {
        String regex = "^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\\d{8}$";
        return phone.matches(regex);
    }
}

4. 编写Controller层接口

创建SmsController.java

package com.example.controller;

import com.example.service.AliyunSmsService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/sms")
public class SmsController {

    @Autowired
    private AliyunSmsService aliyunSmsService;

    /**
     * 发送验证码短信
     * @param phone 手机号
     * @return 发送结果
     */
    @GetMapping("/sendCode/{phone}")
    public String sendVerificationCode(@PathVariable String phone) {
        // 生成随机验证码
        String code = generateRandomCode(6);
        
        // 构建模板参数JSON
        String templateParam = "{\"code\":\"" + code + "\"}";
        
        // 发送短信
        boolean result = aliyunSmsService.sendSms(phone, templateParam);
        
        if (result) {
            // 实际项目中这里需要将验证码存入缓存(Redis等),设置过期时间
            return "短信发送成功,验证码:" + code;
        } else {
            return "短信发送失败";
        }
    }
    
    /**
     * 生成指定长度的随机数字验证码
     * @param length 验证码长度
     * @return 验证码
     */
    private String generateRandomCode(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append((int)(Math.random() * 10));
        }
        return sb.toString();
    }
}

三、高级功能扩展

1. 验证码缓存管理

建议使用Redis存储验证码,设置合理的过期时间:

@Service
public class SmsVerificationService {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    private static final long EXPIRE_TIME = 5 * 60; // 5分钟
    
    public void storeVerificationCode(String phone, String code) {
        redisTemplate.opsForValue().set("sms:code:" + phone, code, EXPIRE_TIME, TimeUnit.SECONDS);
    }
    
    public boolean verifyCode(String phone, String code) {
        String storedCode = redisTemplate.opsForValue().get("sms:code:" + phone);
        return code != null && code.equals(storedCode);
    }
}

2. 发送频率限制

防止恶意刷短信:

public boolean checkSendFrequency(String phone) {
    String key = "sms:limit:" + phone;
    Long count = redisTemplate.opsForValue().increment(key);
    if (count == 1) {
        redisTemplate.expire(key, 1, TimeUnit.HOURS); // 1小时内的限制
    }
    return count <= 5; // 每小时最多发送5条
}

四、使用注意事项

  1. 安全性考虑

    • 避免在代码中硬编码AccessKey和SecretKey
    • 定期更换AccessKey
    • 开启短信服务的IP白名单
  2. 错误处理

    • 完善异常捕获和日志记录
    • 实现重试机制处理临时网络问题
  3. 测试建议

    • 先使用阿里云控制台的"快速学习和测试"功能验证短信服务配置正确
    • 项目测试时,先使用测试手机号

五、完整流程测试

  1. 启动SpringBoot应用
  2. 访问http://localhost:8080/api/sms/sendCode/13800138000发送短信
  3. 检查手机号是否收到短信
  4. 验证功能和错误处理是否正常工作

通过以上步骤,您可以成功实现SpringBoot与阿里云短信服务的整合,实现短信发送功能。