1.登录阿里云搜索短信服务,进来后可以看到主要有以下四个步骤

springboot整合阿里云短信服务demo_spring

第一步申请签名:

springboot整合阿里云短信服务demo_java_02

springboot整合阿里云短信服务demo_redis_03

注意:阿里云目前不支持个人用户申请未上线业务 

签名审核通过之后如下图所示:

springboot整合阿里云短信服务demo_java_04

下一步就是申请短信模板:

springboot整合阿里云短信服务demo_后端_05

 springboot整合阿里云短信服务demo_spring boot_06

审核通过之后如下图所示:(记住模板code,后面会用到)

springboot整合阿里云短信服务demo_spring_07  由于短信发送是我们调用阿里云的api,那么调用阿里云的api要有访问阿里云api的密钥,也就是AccessKey Secret,因此我们要获取到自己的AccessKey Secret

springboot整合阿里云短信服务demo_java_08

springboot整合阿里云短信服务demo_spring boot_09 申请之后可以看到相关内容:

springboot整合阿里云短信服务demo_redis_10

 下面就是springboot来进行整合了:

首先创建项目引入所需要的依赖:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--阿里云短信整合-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--redisTemplate-->
</dependencies>

然后是配置文件里面的一些相关配置:(由于短信验证码会缓存到redis里面,所以还有redis的相关配置)


server.port=7777

##服务名
spring.application.name=hanansheng-sms

##阿里云短信相关配置
aliyun.sms.regionId=default
aliyun.sms.accessKeyId=自己阿里云的accessKeyId
aliyun.sms.secret=自己阿里云的secret

##redis配置
spring.redis.host=自己redis的ip
spring.redis.port=自己的端口号
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0


下面开发短信发送接口:

1、controller:


package com.example.smsboot.smsController;

import com.example.smsboot.service.SmsService;
import com.example.smsboot.util.RandomUtil;
import com.example.smsboot.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

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

@Autowired
private SmsService smsService;

@Autowired
private RedisTemplate<String, String> redisTemplate;

@RequestMapping("send/{phone}")
public Result sendCode(@PathVariable String phone) {
/**
* 判断手机号是否为空
*/
if(StringUtils.isEmpty(phone)){
Assert.isNull(phone,"手机号不允许为空哦");
}
/**
* 发送短信验证码
* 首先从redis里面获取,redis里面能够获取到就直接发送给用户
* 如果redis里面获取不到证明上一条验证码已过期,重新生成验证发给用户
* 目前叮咚买菜app/支付宝就是按照这样的逻辑做的
*/
String code = redisTemplate.opsForValue().get(phone);
if (StringUtils.isEmpty(code)) {
code = RandomUtil.getSixBitRandom();
}
/**
* 拿到phone、和code进行验证码发送
*/
boolean isSend = smsService.sendSms(phone, code);
if(isSend){
/**
* 放到redis里面
*/
redisTemplate.opsForValue().set(phone,code,2, TimeUnit.MINUTES);
return Result.ok();
}else{
return Result.fail().message("发送短信失败");
}


}


}


2、serviceImpl:


package com.example.smsboot.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.example.smsboot.service.SmsService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class SmsServiceImpl implements SmsService {

/**
* 获取配置文件中阿里云相关信息
*/
@Value("${aliyun.sms.regionId}")
private String regionId;

@Value("${aliyun.sms.accessKeyId}")
private String accessKeyId;

@Value("${aliyun.sms.secret}")
private String secret;

@Override
public boolean sendSms(String phone, String code) {
// 整合阿里云短信服务发送
// 设置相关参数
DefaultProfile profile = DefaultProfile.getProfile(regionId,accessKeyId,secret);
IAcsClient client = new DefaultAcsClient(profile);
// 创建通用的请求对象
CommonRequest request = new CommonRequest();
// 指定请求方式
request.setMethod(MethodType.POST);
// 固定写法阿里云短信地址
request.setDomain("dysmsapi.aliyuncs.com");
// 签名算法版本 固定
request.setVersion("2017-05-25");
// 请求api的名称
request.setAction("SendSms");

//手机号--下面几个参数key值不允许修改
request.putQueryParameter("PhoneNumbers", phone);
//签名名称
request.putQueryParameter("SignName", "阿里云短信测试");
//模板code
request.putQueryParameter("TemplateCode", "自己模板code");
//验证码 使用json格式 {"code":"123456"}
Map<String,Object> param = new HashMap();
param.put("code",code);
request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param));
// 调用方法进行发送短信
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
return response.getHttpResponse().isSuccess();
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return false;
}
}


我使用浏览器访问显示发送成功:

springboot整合阿里云短信服务demo_spring boot_11

我看了下手机确实有收到验证码:

springboot整合阿里云短信服务demo_spring boot_12

然后我去redis缓存里面看下是否已经成功添加到了缓存中:

springboot整合阿里云短信服务demo_java_13 

可以看到成功存到redis里面,由于我设置的缓存有效期是两分钟,两分钟后缓存自动失效。

demo中用到的对返回信息统一封装类可以看这篇文章

其中还用到了一个生成六位验证码的工具类,代码如下:

package com.example.smsboot.util;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

public class RandomUtil {

private static final Random random = new Random();

private static final DecimalFormat fourdf = new DecimalFormat("0000");

private static final DecimalFormat sixdf = new DecimalFormat("000000");

public static String getFourBitRandom() {
return fourdf.format(random.nextInt(10000));
}

public static String getSixBitRandom() {
return sixdf.format(random.nextInt(1000000));
}

/**
* 给定数组,抽取n个数据
* @param list
* @param n
* @return
*/
public static ArrayList getRandom(List list, int n) {

Random random = new Random();

HashMap<Object, Object> hashMap = new HashMap<Object, Object>();

// 生成随机数字并存入HashMap
for (int i = 0; i < list.size(); i++) {

int number = random.nextInt(100) + 1;

hashMap.put(number, i);
}

// 从HashMap导入数组
Object[] robjs = hashMap.values().toArray();

ArrayList r = new ArrayList();

// 遍历数组并打印数据
for (int i = 0; i < n; i++) {
r.add(list.get((int) robjs[i]));
System.out.print(list.get((int) robjs[i]) + "\t");
}
System.out.print("\n");
return r;
}
}