發送短信測試
創建aldy_demo的jar工程
導入依賴信息
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
參考阿里雲短信服務的api短信服務api
創建demo類測試發送短信
public class SmsDemo {
//產品名稱:雲通信短信API產品,開發者無需替換
static final String product = "Dysmsapi";
//產品域名,開發者無需替換
static final String domain = "dysmsapi.aliyuncs.com";
//此處需要替換成開發者自己的AK(在阿里雲訪問控制檯尋找)
static final String accessKeyId = "";
static final String accessKeySecret = "";
public static SendSmsResponse sendSms() throws ClientException {
//可自助調整超時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暫不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//組裝請求對象-具體描述見控制檯-文檔部分內容
SendSmsRequest request = new SendSmsRequest();
//必填:待發送手機號
request.setPhoneNumbers("");
//必填:短信簽名-可在短信控制檯中找到
request.setSignName("");
//必填:短信模板-可在短信控制檯中找到
request.setTemplateCode("");
//可選:模板中的變量替換JSON串,如模板內容爲"親愛的${name},您的驗證碼爲${code}"時,此處的值爲
request.setTemplateParam("{\"code\":\"666888\"}");
//hint 此處可能會拋出異常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
return sendSmsResponse;
}
public static void main(String[] args) throws ClientException, InterruptedException {
//發短信
SendSmsResponse response = sendSms();
System.out.println("短信接口返回的數據----------------");
System.out.println("Code=" + response.getCode());
System.out.println("Message=" + response.getMessage());
System.out.println("RequestId=" + response.getRequestId());
System.out.println("BizId=" + response.getBizId());
}
}
運行測試類向自己手機上發送一條驗證碼
微服務搭建
構建一個通用的短信發送服務(spring boot),接收activeMQ的消息(MAP類型)消息包括手機號(mobile)、短信模板號(template_code)、簽名(sign_name)、參數字符串(param)
AcitiveMQ的消息類型是點對點的隊列消息
創建一個jar工程youlexuan_sms
pom依賴信息
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!-- 阿里大於-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
創建引導類,放在包的根目錄下
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
創建配置文件application.properties
server.port = 8888
spring.activemq.broker-url=tcp://192.168.2.123:61616
accessKeyId = *********
accessKeySecret = ********
抽取短信工具類(原來短信測試類的靜態方法改成非靜態的,因爲是工具類,所以會通過工具類調用方法,所以沒必要是靜態方法;抽取出來的param字段要求是json格式的)
@Component
public class SmsUtil {
@Value("${accessKeyId}")
private String accessKeyId;
@Value("${accessKeySecret}")
private String accessKeySecret;
//產品名稱:雲通信短信API產品,開發者無需替換
static final String product = "Dysmsapi";
//產品域名,開發者無需替換
static final String domain = "dysmsapi.aliyuncs.com";
public SendSmsResponse sendSms(String phone, String sign, String templateId, String param) throws ClientException {
//可自助調整超時時間
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
//初始化acsClient,暫不支持region化
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
//組裝請求對象-具體描述見控制檯-文檔部分內容
SendSmsRequest request = new SendSmsRequest();
//必填:待發送手機號
request.setPhoneNumbers(phone);
//必填:短信簽名-可在短信控制檯中找到
request.setSignName(sign);
//必填:短信模板-可在短信控制檯中找到
request.setTemplateCode(templateId);
//可選:模板中的變量替換JSON串,如模板內容爲"親愛的${name},您的驗證碼爲${code}"時,此處的值爲
request.setTemplateParam(param);
//hint 此處可能會拋出異常,注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
return sendSmsResponse;
}
}
創建SmsListener類:
@Component
public class SmsListener {
@Autowired
private SmsUtil smsUtil;
@JmsListener(destination = "smsDestination")
public void sendSms(Map<String, String> map) {
try {
String phone = map.get("phone");
String sign = map.get("sign");
String templateId = map.get("templateId");
String param = map.get("param");
System.out.println(">>>>>receive msg: phone" + phone + ", sign: " + sign + ", templateId: " + templateId + ",param: " + param);
SendSmsResponse sendSmsResponse = smsUtil.sendSms(phone, sign, templateId, param);
System.out.println(">>>>>sms_service send sms result: " + sendSmsResponse.getCode());
} catch (ClientException e) {
e.printStackTrace();
}
}
}
這樣發送短信的微服務我們就搭建好了,下面只需要在用戶controller層以及service層進行生成驗證碼以及發送AcitiveMQ的消息
配置user_service工程下的spring-jms-producer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.weilinyang" />
<!-- 產生Connection的ConnectionFactory,由對應的 JMS服務廠商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.2.123:61616" />
</bean>
<!-- Spring用於管理ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="targetConnectionFactory" />
</bean>
<!-- Spring提供的JMS工具類,它可以進行消息發送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
</bean>
<!-- 隊列目的地,點對點信息 -->
<bean id="smsDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="sms_queue" />
</bean>
</beans>
@Reference
private UserService userService;
@RequestMapping("/sendCode")
public Result sendCode(String phone){
if (!PhoneFormatCheckUtils.isChinaPhoneLegal(phone)){
return new Result(false,"手機號非法!");
}
try {
userService.createSmsCode(phone);
return new Result(false,"短信發送成功!");
} catch (Exception e) {
e.printStackTrace();
return new Result(false,"短信發送異常!");
}
}
@Value("${sign}")
private String sign;
@Value("${templateId}")
private String templateId;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private JmsTemplate jmsTemplate;
@Override
public void createSmsCode(String phone) {
//Math.random() 範圍[0,1)
//1、生成6位驗證碼 100000-999999
int num = (int)(Math.random() * 900000 + 100000);
System.out.println("生成的驗證碼爲"+num);
Map<String,String> map = new HashMap<>();
map.put("param","{\"code\":\"" + num + "\"}");
map.put("phone",phone);
map.put("sign",sign);
map.put("templateId",templateId);
// 2. 將驗證碼在 redis 中保存起來,以便註冊時候校驗
redisTemplate.boundHashOps("register_code").put("code",num);
System.out.println("存入redis");
// 3. 發送驗證碼:通過向消息中間件發送消息,來驅動 sms_service 短信服務幫你發驗證碼
jmsTemplate.convertAndSend("smsDestination",map);
System.out.println("已發送actMQ");
}
驗證碼的校驗
驗證碼的保存
驗證碼保存在redis數據庫中,當用戶點擊註冊時,我們再去redis庫中查詢與前端提交的進行比對
@RequestMapping("/add")
public Result addUser(@RequestBody TbUser user, String code){
//校驗驗證碼
Integer redisCode = (Integer) redisTemplate.boundHashOps("register_code").get("code");
try {
if (Integer.parseInt(code)!=redisCode){
return new Result(false,"驗證碼錯誤!");
}
// 設置註冊時的一些默認信息
user.setCreated(new Date());
user.setUpdated(new Date());
// 密碼加密 md5
user.setPassword(DigestUtils.md5Hex(user.getPassword()));
userService.addUser(user);
return new Result(true,"註冊成功!");
} catch (Exception e) {
e.printStackTrace();
return new Result(false,"註冊失敗!");
}
}