短信微服務

發送短信測試

創建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,"註冊失敗!");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章