天天看點

短信工具類4.使用者注冊

package cn.itcast.sms;

import com.aliyuncs.DefaultAcsClient;

import com.aliyuncs.IAcsClient;

import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsRequest;

import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;

import com.aliyuncs.exceptions.ClientException;

import com.aliyuncs.profile.DefaultProfile;

import com.aliyuncs.profile.IClientProfile;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.core.env.Environment;

import org.springframework.stereotype.Component;

@Component

public class SmsUtil {

    //産品名稱:雲通信短信API産品,開發者無需替換

    static final String product = "Dysmsapi";

    //産品域名,開發者無需替換

    static final String domain = "dysmsapi.aliyuncs.com";

    @Autowired

    private Environment env;

    // TODO 此處需要替換成開發者自己的AK(在阿裡雲通路控制台尋找)

    public SendSmsResponse sendSms(String mobile,String template_code,String sign_name,String param) throws ClientException {

     String accessKeyId =env.getProperty("accessKeyId");

        String accessKeySecret = env.getProperty("accessKeySecret");

        //可自助調整逾時時間

        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(mobile);

        //必填:短信簽名-可在短信控制台中找到

        request.setSignName(sign_name);

        //必填:短信模闆-可在短信控制台中找到

        request.setTemplateCode(template_code);

        //可選:模闆中的變量替換JSON串,如模闆内容為"親愛的${name},您的驗證碼為${code}"時,此處的值為

        request.setTemplateParam(param);

        //選填-上行短信擴充碼(無特殊需求使用者請忽略此字段)

        //request.setSmsUpExtendCode("90997");

        //可選:outId為提供給業務方擴充字段,最終在短信回執消息中将此值帶回給調用者

        request.setOutId("yourOutId");

        //hint 此處可能會抛出異常,注意catch

        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

        return sendSmsResponse;

    }

    public  QuerySendDetailsResponse querySendDetails(String mobile,String bizId) throws ClientException {

     String accessKeyId =env.getProperty("accessKeyId");

        String accessKeySecret = env.getProperty("accessKeySecret");

        //可自助調整逾時時間

        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);

        //組裝請求對象

        QuerySendDetailsRequest request = new QuerySendDetailsRequest();

        //必填-号碼

        request.setPhoneNumber(mobile);

        //可選-流水号

        request.setBizId(bizId);

        //必填-發送日期 支援30天内記錄查詢,格式yyyyMMdd

        SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd");

        request.setSendDate(ft.format(new Date()));

        //必填-頁大小

        request.setPageSize(10L);

        //必填-目前頁碼從1開始計數

        request.setCurrentPage(1L);

        //hint 此處可能會抛出異常,注意catch

        QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request);

        return querySendDetailsResponse;

    }

}

3.2.3消息監聽類

建立SmsListener.java

package cn.itcast.sms;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jms.annotation.JmsListener;

import org.springframework.stereotype.Component;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;

import com.aliyuncs.exceptions.ClientException;

@Component

public class SmsListener {

@Autowired

private SmsUtil smsUtil;

@JmsListener(destination="sms")

public void sendSms(Map<String,String> map){

try {

SendSmsResponse response = smsUtil.sendSms(

map.get("mobile"),

map.get("template_code"),

map.get("sign_name"),

map.get("param")  );  

    System.out.println("Code=" + response.getCode());

        System.out.println("Message=" + response.getMessage());

        System.out.println("RequestId=" + response.getRequestId());

        System.out.println("BizId=" + response.getBizId());

} catch (ClientException e) {

e.printStackTrace();

}

}

}

3.3代碼測試

修改springboot-demo  的QueueController.java

@RequestMapping("/sendsms")

public void sendSms(){

Map map=new HashMap<>();

map.put("mobile", "13900001111");

map.put("template_code", "SMS_85735065");

map.put("sign_name", "黑馬");

map.put("param", "{\"number\":\"102931\"}");

jmsMessagingTemplate.convertAndSend("sms",map);

}

啟動itcast_sms

啟動springboot-demo

位址欄輸入:http://localhost:8088/sendsms.do 

觀察控制台輸出

随後短信也成功發送到你的手機上

4.使用者注冊

4.1需求分析

完成使用者注冊功能

4.2工程搭建

4.2.1使用者服務接口層

(1)建立pinyougou-user-interface(jar)

(2)引入pojo依賴

4.2.2使用者服務實作層

(1)建立pinyougou-user-service(war)

(2)引入spring  dubbox   activeMQ相關依賴,引入依賴( pinyougou-user-interface  pinyougou-dao  pinyougou-common),運作端口為9006

(3)添加web.xml  

(4)建立Spring 配置檔案applicationContext-service.xml 和applicationContent-tx.xml

    <dubbo:protocol name="dubbo" port="20886" />

    <dubbo:annotation package="com.pinyougou.user.service.impl" />  

<dubbo:application name="pinyougou-user-service"/>  

    <dubbo:registry address="zookeeper://192.168.25.135:2181"/>

4.2.3使用者中心WEB層

建立war工程  pinyougou-user-web 我們将注冊功能放入此工程

(1)添加web.xml

(2)引入依賴pinyougou-user-interface 、spring相關依賴(參照其它web工程),tomcat運作端口9106

(3)添加spring配置檔案

(4)拷貝靜态原型頁面register.html 及相關資源

4.3基本注冊功能實作

4.3.2後端服務實作層

修改pinyougou-user-service的UserServiceImpl.java

@Override

public void add(TbUser user) {

user.setCreated(new Date());//建立日期

user.setUpdated(new Date());//修改日期

String password = DigestUtils.md5Hex(user.getPassword());//對密碼加密

user.setPassword(password);

userMapper.insert(user);

}

4.3.3前端控制層

修改userController.js

 //控制層

app.controller('userController' ,function($scope,$controller   ,userService){

//注冊

$scope.reg=function(){

    if($scope.entity.password!=$scope.password)  {

       alert("兩次輸入的密碼不一緻,請重新輸入");     

       return ;

    }

userService.add( $scope.entity  ).success(

function(response){

alert(response.message);

}

);

}    

});

4.3.4修改頁面

修改頁面register.html ,引入js

<script type="text/javascript" src="plugins/angularjs/angular.min.js"></script>

<script type="text/javascript" src="js/base.js"></script>

<script type="text/javascript" src="js/service/userService.js"></script>

<script type="text/javascript" src="js/controller/userController.js"></script>

指令

<body ng-app="pinyougou" ng-controller="userController" >

綁定表單

<form class="sui-form form-horizontal">

<div class="control-group">

<label class="control-label">使用者名:</label>

<div class="controls">

<input type="text" placeholder="請輸入你的使用者名" ng-model="entity.username" class="input-xfat input-xlarge">

</div>

</div>

<div class="control-group">

   <label for="inputPassword" class="control-label">登入密碼:</label>

<div class="controls">

<input type="password" placeholder="設定登入密碼" ng-model="entity.password" class="input-xfat input-xlarge">

</div>

</div>

<div class="control-group">

<label for="inputPassword" class="control-label">确認密碼:</label>

<div class="controls">

<input type="password" placeholder="再次确認密碼" ng-model="password" class="input-xfat input-xlarge">

</div>

</div>

<div class="control-group">

<label class="control-label">手機号:</label>

<div class="controls">

<input type="text" placeholder="請輸入你的手機号" ng-model="entity.phone" class="input-xfat input-xlarge">

</div>

</div>

<div class="control-group">

<label for="inputPassword" class="control-label">短信驗證碼:</label>

<div class="controls">

<input type="text" placeholder="短信驗證碼" class="input-xfat input-xlarge">  <a href="#">擷取短信驗證碼</a>

</div>

</div>

<div class="control-group">

<label for="inputPassword" class="control-label">      </label>

<div class="controls">

<input name="m1" type="checkbox" value="2" checked=""><span>同意協定并注冊《品優購使用者協定》</span>

</div>

</div>

<div class="control-group">

<label class="control-label"></label>

<div class="controls btn-reg">

<a class="sui-btn btn-block btn-xlarge btn-danger" ng-click="reg()" target="_blank">完成注冊</a>

</div>

</div>

</form>

4.4 注冊判斷短信驗證碼

4.4.1實作思路

點選頁面上的”擷取短信驗證碼”連接配接,向後端傳遞手機号。後端随機生成6位數字作為短信驗證碼,将其儲存在redis中(手機号作為KEY),并發送到短信網關。

使用者注冊時,後端根據手機号查詢redis中的驗證碼與使用者填寫的驗證碼是否相同,如果不同則提示使用者不能注冊。

4.4.2生成驗證碼

(1)修改pinyougou-user-interface工程UserService.java  ,增加方法

public void createSmsCode(String phone);

(2)修改pinyougou-user-service工程的UserServiceImpl.java

@Autowired

private RedisTemplate<String , Object> redisTemplate;

public void createSmsCode(String phone){

//生成6位随機數

String code =  (long) (Math.random()*1000000)+"";

System.out.println("驗證碼:"+code);

//存入緩存

redisTemplate.boundHashOps("smscode").put(phone, code);

//發送到activeMQ ....

}

(3)在 pinyougou-common  添加工具類PhoneFormatCheckUtils.java,用于驗證手機号

(4)修改pinyougou-user-web的UserController.java

@RequestMapping("/sendCode")

public Result sendCode(String phone){

//判斷手機号格式

if(!PhoneFormatCheckUtils.isPhoneLegal(phone)){

return new Result(false, "手機号格式不正确");

}

try {

userService.createSmsCode(phone);//生成驗證碼

return new Result(true, "驗證碼發送成功");

} catch (Exception e) {

e.printStackTrace();

return new Result(true, "驗證碼發送失敗");

}

}

  1. pinyougou-user-web的userService.js

//發送驗證碼

this.sendCode=function(phone){

return $http.get("../user/sendCode.do?phone="+phone);

}

  1. pinyougou-user-web的userController.js

//發送驗證碼

$scope.sendCode=function(){

if($scope.entity.phone==null){

alert("請輸入手機号!");

return ;

}

userService.sendCode($scope.entity.phone).success(

function(response){

alert(response.message);

}

);

}

  1. 修改頁面register.html
<a ng-click="sendCode()" >擷取短信驗證碼</a>

4.4.3使用者注冊判斷驗證碼

(1)修改pinyougou-user-interface的UserService.java

public boolean  checkSmsCode(String phone,String code);

(2)修改pinyougou-user-service的 UserServiceImpl.java

public boolean  checkSmsCode(String phone,String code){

//得到緩存中存儲的驗證碼

String sysCode = (String) redisTemplate.boundHashOps("smscode").get(phone);

if(sysCode==null){

return false;

}

if(!sysCode.equals(code)){

return false;

}

return true;

}

(3)修改pinyougou-user-web的UserController.java

@RequestMapping("/add")

public Result add(@RequestBody TbUser user,String smscode){

boolean checkSmsCode = userService.checkSmsCode(user.getPhone(), smscode);

if(checkSmsCode==false){

return new Result(false, "驗證碼輸入錯誤!");

}

try {

userService.add(user);

return new Result(true, "增加成功");

} catch (Exception e) {

e.printStackTrace();

return new Result(false, "增加失敗");

}

}

  1. 修改pinyougou-user-web的userService.js

//增加

this.add=function(entity,smscode){

return  $http.post('../user/add.do?smscode='+smscode ,entity );

}

  1. 修改pinyougou-portal-web 的UserController.java

//儲存

$scope.reg=function(){

userService.add( $scope.entity, $scope.smscode  ).success(

function(response){

alert(response.message);

}

);

}

(6)修改頁面,綁定變量

<input type="text" placeholder="短信驗證碼" ng-model="smscode" class="input-xfat input-xlarge">  <a href="#" ng-click="sendCode()">擷取短信驗證碼</a>

4.4.4短信驗證碼發送到手機

(1)在pinyougou-user-service添加配置檔案applicationContext-activemq.xml

    <!-- 真正可以産生Connection的ConnectionFactory,由對應的 JMS服務廠商提供-->  

<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">  

    <property name="brokerURL" value="tcp://192.168.25.135:61616"/>  

</bean> 

    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->  

<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">  

<!-- 目标ConnectionFactory對應真實的可以産生JMS Connection的ConnectionFactory -->  

    <property name="targetConnectionFactory" ref="targetConnectionFactory"/>  

</bean>     

    <!-- Spring提供的JMS工具類,它可以進行消息發送、接收等 -->  

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">  

    <!-- 這個connectionFactory對應的是我們定義的Spring提供的那個ConnectionFactory對象 -->  

    <property name="connectionFactory" ref="connectionFactory"/>  

</bean>      

<!--這個是點對點消息  -->  

<bean id="smsDestination" class="org.apache.activemq.command.ActiveMQQueue">  

    <constructor-arg value="sms"/>  

</bean>  

(2)修改pinyougou-user-service的UserServiceImpl.java

@Autowired

private JmsTemplate jmsTemplate;

@Autowired

private Destination smsDestination;

@Value("${template_code}")

private String template_code;

@Value("${sign_name}")

private String sign_name;

public void createSmsCode(final String phone){

//生成6位随機數

final String code =  (long) (Math.random()*1000000)+"";

System.out.println("驗證碼:"+code);

//存入緩存

redisTemplate.boundHashOps("smscode").put(phone, code);

//發送到activeMQ

jmsTemplate.send(smsDestination, new MessageCreator() {

@Override

public Message createMessage(Session session) throws JMSException {

MapMessage mapMessage = session.createMapMessage();

mapMessage.setString("mobile", phone);//手機号

mapMessage.setString("template_code", "SMS_85735065");//模闆編号

mapMessage.setString("sign_name", "黑馬");//簽名

Map m=new HashMap<>();

m.put("number", code);

mapMessage.setString("param", JSON.toJSONString(m));//參數

return mapMessage;

}

});

}

(3)在pinyougou-common的properties目錄下建立配置檔案sms.properties

template_code=SMS_85735065

sign_name=\u9ED1\u9A6C

繼續閱讀