品優(yōu)購電商系統(tǒng)開發(fā) 第14章 SpringBoot框架與短信解決方案(品優(yōu)購前端項目)
課程目標(biāo)
目標(biāo)1:掌握Spring boot框架的搭建方法
目標(biāo)2:能夠使用阿里大于發(fā)送短信
目標(biāo)3:運用SpringBoot、阿里大于和ActiveMQ 開發(fā)短信微服務(wù)
目標(biāo)4:完成品優(yōu)購用戶注冊功能(短信驗證碼認證)
1.Spring Boot入門
1.1什么是Spring Boot
Spring 誕生時是 java 企業(yè)版(Java Enterprise Edition,JEE,也稱 J2EE)的輕量級代替品。無需開發(fā)重量級的 Enterprise JavaBean(EJB),Spring 為企業(yè)級Java 開發(fā)提供了一種相對簡單的方法,通過依賴注入和面向切面編程,用簡單的Java 對象(Plain Old Java Object,POJO)實現(xiàn)了 EJB 的功能。
雖然 Spring 的組件代碼是輕量級的,但它的配置卻是重量級的。一開始,Spring 用 XML 配置,而且是很多 XML 配置。Spring 2.5 引入了基于注解的組件掃描,這消除了大量針對應(yīng)用程序自身組件的顯式 XML 配置。Spring 3.0 引入了基于 Java 的配置,這是一種類型安全的可重構(gòu)配置方式,可以代替 XML。所有這些配置都代表了開發(fā)時的損耗。因為在思考 Spring 特性配置和解決業(yè)務(wù)問題之間需要進行思維切換,所以寫配置擠占了寫應(yīng)用程序邏輯的時間。和所有框架一樣,Spring 實用,但與此同時它要求的回報也不少。
除此之外,項目的依賴管理也是件吃力不討好的事情。決定項目里要用哪些庫就已經(jīng)夠讓人頭痛的了,你還要知道這些庫的哪個版本和其他庫不會有沖突,這難題實在太棘手。并且,依賴管理也是一種損耗,添加依賴不是寫應(yīng)用程序代碼。一旦選錯了依賴的版本,隨之而來的不兼容問題毫無疑問會是生產(chǎn)力殺手。
Spring Boot 讓這一切成為了過去。
Spring Boot 是 Spring 社區(qū)較新的一個項目。該項目的目的是幫助開發(fā)者更容易的創(chuàng)建基于 Spring 的應(yīng)用程序和服務(wù),讓更多人的人更快的對 Spring 進行入門體驗,為 Spring 生態(tài)系統(tǒng)提供了一種固定的、約定優(yōu)于配置風(fēng)格的框架。
Spring Boot 具有如下特性:
(1)為基于 Spring 的開發(fā)提供更快的入門體驗
(2)開箱即用,沒有代碼生成,也無需 XML 配置。同時也可以修改默認值來滿足特定的需求。
(3)提供了一些大型項目中常見的非功能性特性,如嵌入式服務(wù)器、安全、指標(biāo),健康檢測、外部配置等。
(4)Spring Boot 并不是不對 Spring 功能上的增強,而是提供了一種快速使用 Spring 的方式。
1.2 Spring Boot入門小Demo
1.2.1起步依賴
創(chuàng)建Maven工程 springboot_demo(打包方式j(luò)ar)
在pom.xml中添加如下依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId><version>1.4.0.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
我們會驚奇地發(fā)現(xiàn),我們的工程自動添加了好多好多jar包
…
而這些jar包正式我們做開發(fā)時需要導(dǎo)入的jar包。因為這些jar包被我們剛才引入的spring-boot-starter-web所引用了,所以我們引用spring-boot-starter-web后會自動把依賴傳遞過來。
1.2.2變更JDK版本
我們發(fā)現(xiàn)默認情況下工程的JDK版本是1.6 ,而我們通常用使用1.7的版本,所以我們需要在pom.xml中添加以下配置
<properties> <java.version>1.7</java.version> </properties>
添加后更新工程,會發(fā)現(xiàn)版本已經(jīng)變更為1.7
1.2.3引導(dǎo)類
只需要創(chuàng)建一個引導(dǎo)類 .
package cn.itcast.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
簡單解釋一下,@SpringBootApplication其實就是以下三個注解的總和
@Configuration: 用于定義一個配置類
@EnableAutoConfiguration :Spring Boot會自動根據(jù)你jar包的依賴來自動配置項目。
@ComponentScan: 告訴Spring 哪個packages 的用注解標(biāo)識的類 會被spring自動掃描并且裝入bean容器。
我們直接執(zhí)行這個引導(dǎo)類,會發(fā)現(xiàn)控制臺出現(xiàn)的這個標(biāo)識
你能不能看出來上邊這個圖是什么東西?
1.2.4 Spring MVC實現(xiàn)Hello World輸出
我們現(xiàn)在開始使用spring MVC框架,實現(xiàn)json數(shù)據(jù)的輸出。如果按照我們原來的做法,需要在web.xml中添加一個DispatcherServlet的配置,再添加一個spring的配置文件,配置文件中需要添加如下配置
<!– 使用組件掃描,不用將controller在spring中配置 –> <context:component-scan base-package=”cn.itcast.demo.controller” /> <!– 使用注解驅(qū)動不用在下邊定義映射器和適配置器 –> <mvc:annotation-driven> <mvc:message-converters register-defaults=”true”> <bean class=”com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter”> <property name=”supportedMediaTypes” value=”application/json”/> <property name=”features”> <array> <value>WriteMapNullValue</value> <value>WriteDateUseDateFormat</value> </array> </property> </bean> </mvc:Message-converters> </mvc:annotation-driven>
但是我們用SpringBoot,這一切都省了。我們直接寫Controller類
package cn.itcast.demo.controller;import org.springframework.web.bind.annotation.requestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class HelloWorldController { @RequestMapping(“/info”) public String info(){ return “HelloWorld”; } }
我們運行啟動類來運行程序
在瀏覽器地址欄輸入 http://localhost:8080/info 即可看到運行結(jié)果
1.2.5修改tomcat啟動端口
在src/main/resources下創(chuàng)建application.properties
server.port=8088
重新運行引導(dǎo)類。地址欄輸入
http://localhost:8088/info
1.2.6讀取配置文件信息
在src/main/resources下的application.properties 增加配置
url=http://www.itcast.cn
我要在類中讀取這個配置信息,修改HelloWorldController
@Autowired private Environment env; @RequestMapping(“/info”) public String info(){ return “HelloWorld~~” env.getProperty(“url”); }
1.2.7熱部署
我們在開發(fā)中反復(fù)修改類、頁面等資源,每次修改后都是需要重新啟動才生效,這樣每次啟動都很麻煩,浪費了大量的時間,能不能在我修改代碼后不重啟就能生效呢?可以,在pom.xml中添加如下配置就可以實現(xiàn)這樣的功能,我們稱之為熱部署。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
趕快試試看吧,是不是很爽。
1.3 Spring Boot與ActiveMQ整合
1.3.1使用內(nèi)嵌服務(wù)
(1)在pom.xml中引入ActiveMQ起步依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId></dependency>
(2)創(chuàng)建消息生產(chǎn)者
/** * 消息生產(chǎn)者 * @author Administrator */@RestControllerpublic class QueueController { @Autowired private JmsMessagingTemplate jmsMessagingTemplate; @RequestMapping(“/send”) public void send(String text){ jmsMessagingTemplate.convertAndSend(“itcast”, text); }}
(3)創(chuàng)建消息消費者
@Componentpublic class Consumer { @JmsListener(destination=”itcast”) public void readMessage(String text){ System.out.println(“接收到消息:” text); } }
測試:啟動服務(wù)后,在瀏覽器執(zhí)行
http://localhost:8088/send.do?text=aaaaa
即可看到控制臺輸出消息提示。Spring Boot內(nèi)置了ActiveMQ的服務(wù),所以我們不用單獨啟動也可以執(zhí)行應(yīng)用程序。
1.3.2使用外部服務(wù)
在src/main/resources下的application.properties增加配置, 指定ActiveMQ的地址
spring.activemq.broker-url=tcp://192.168.25.135:61616
運行后,會在activeMQ中看到發(fā)送的queue
1.3.3發(fā)送Map信息
(1)修改QueueController.java
@RequestMapping(“/sendmap”) public void sendMap(){ Map map=new HashMap<>(); map.put(“mobile”, “13900001111”); map.put(“content”, “恭喜獲得10元代金券”); jmsMessagingTemplate.convertAndSend(“itcast_map”,map); }
(2)修改Consumer.java
@JmsListener(destination=”itcast_map”) public void readMap(Map map){ System.out.println(map); }
2.短信發(fā)送平臺-阿里大于
2.1阿里大于簡介
阿里大于是阿里云旗下產(chǎn)品,融合了三大運營商的通信能力,通過將傳統(tǒng)通信業(yè)務(wù)和能力與互聯(lián)網(wǎng)相結(jié)合,創(chuàng)新融合阿里巴巴生態(tài)內(nèi)容,全力為中小企業(yè)和開發(fā)者提供優(yōu)質(zhì)服務(wù)阿里大于提供包括短信、語音、流量直充、私密專線、店鋪手機號等個性化服務(wù)。通過阿里大于打通三大運營商通信能力,全面融合阿里巴巴生態(tài),以開放API及SDK的方式向開發(fā)者提供通信和數(shù)據(jù)服務(wù),更好地支撐企業(yè)業(yè)務(wù)發(fā)展和創(chuàng)新服務(wù)。
2.2準(zhǔn)備工作
2.2.1注冊賬戶
首先我們先進入“阿里大于” www.alidayu.com (https://dayu.aliyun.com/)
注冊賬號后,再在手機下載“阿里云”應(yīng)用,登陸,然后進行在線實名認證。
2.2.2登陸系統(tǒng)
使用剛才注冊的賬號進行登陸。
點擊進入控制臺
點擊使用短信服務(wù)
3.2.3申請簽名
3.2.4申請模板
3.2.5創(chuàng)建accessKey
3.3 SDK安裝
從阿里云通信官網(wǎng)上下載Demo工程
解壓后導(dǎo)入Eclipce
紅線框起來的兩個工程就是阿里云通信的依賴jar源碼,我們將其安裝到本地倉庫
(刪除aliyun-java-sdk-core的單元測試類)
本地jar包安裝后 alicom-dysms-api工程引入依賴
<dependencies> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.2.5</version> </dependency></dependencies>
紅叉消失了
3.4發(fā)送短信測試
(1)打開SmsDemo
替換下列幾處代碼
這個accessKeyId和accessSecret到剛才申請過的
手機號,短信簽名和模板號
模板參數(shù)
number是我們申請模板時寫的參數(shù)
執(zhí)行main方法我們就可以在手機收到短信啦
3.短信微服務(wù)
3.1需求分析
構(gòu)建一個通用的短信發(fā)送服務(wù)(獨立于品優(yōu)購的單獨工程),接收activeMQ的消息(MAP類型) 消息包括手機號(mobile)、短信模板號(template_code)、簽名(sign_name)、參數(shù)字符串(param )
3.2代碼實現(xiàn)
3.2.1工程搭建
(1)創(chuàng)建工程itcast_sms (JAR工程),POM文件引入依賴
<properties> <java.version>1.7</java.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.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-dysmsapi</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.2.5</version> </dependency> </dependencies>
(2)創(chuàng)建引導(dǎo)類
package cn.itcast.sms;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
(3)創(chuàng)建配置文件application.properties
server.port=9003spring.activemq.broker-url=tcp://192.168.25.135:61616accessKeyId=不告訴你accessKeySecret=不告訴你
3.2.2短信工具類
參照之前的短信demo創(chuàng)建短信工具類
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;/** * 短信工具類 * @author Administrator * */@Componentpublic class SmsUtil { //產(chǎn)品名稱:云通信短信API產(chǎn)品,開發(fā)者無需替換 static final String product = “Dysmsapi”; //產(chǎn)品域名,開發(fā)者無需替換 static final String domain = “dysmsapi.aliyuncs.com”; @Autowired private Environment env; // TODO 此處需要替換成開發(fā)者自己的AK(在阿里云訪問控制臺尋找) /** * 發(fā)送短信 * @param mobile 手機號 * @param template_code 模板號 * @param sign_name 簽名 * @param param 參數(shù) * @return * @throws ClientException */ 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”); //可自助調(diào)整超時時間 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); //組裝請求對象-具體描述見控制臺-文檔部分內(nèi)容 SendSmsRequest request = new SendSmsRequest(); //必填:待發(fā)送手機號 request.setPhoneNumbers(mobile); //必填:短信簽名-可在短信控制臺中找到 request.setSignName(sign_name); //必填:短信模板-可在短信控制臺中找到 request.setTemplateCode(template_code); //可選:模板中的變量替換JSON串,如模板內(nèi)容為”親愛的${name},您的驗證碼為${code}”時,此處的值為 request.setTemplateParam(param); //選填-上行短信擴展碼(無特殊需求用戶請忽略此字段) //request.setSmsUpExtendCode(“90997”); //可選:outId為提供給業(yè)務(wù)方擴展字段,最終在短信回執(zhí)消息中將此值帶回給調(diào)用者 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”); //可自助調(diào)整超時時間 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); //必填-發(fā)送日期 支持30天內(nèi)記錄查詢,格式y(tǒng)yyyMMdd SimpleDateFormat ft = new SimpleDateFormat(“yyyyMMdd”); request.setSendDate(ft.format(new Date())); //必填-頁大小 request.setPageSize(10L); //必填-當(dāng)前頁碼從1開始計數(shù) request.setCurrentPage(1L); //hint 此處可能會拋出異常,注意catch QuerySendDetailsResponse querySendDetailsResponse = acsClient.getAcsResponse(request); return querySendDetailsResponse; }}
3.2.3消息監(jiān)聽類
創(chuàng)建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;/** * 消息監(jiān)聽類 * @author Administrator */@Componentpublic 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
觀察控制臺輸出
隨后短信也成功發(fā)送到你的手機上
4.用戶注冊
4.1需求分析
完成用戶注冊功能
4.2工程搭建
4.2.1用戶服務(wù)接口層
(1)創(chuàng)建pinyougou-user-interface(jar)
(2)引入pojo依賴
4.2.2用戶服務(wù)實現(xiàn)層
(1)創(chuàng)建pinyougou-user-service(war)
(2)引入spring dubbox activeMQ相關(guān)依賴,引入依賴( pinyougou-user-interface pinyougou-dao pinyougou-common),運行端口為9006
(3)添加web.xml
(4)創(chuàng)建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層
創(chuàng)建war工程 pinyougou-user-web 我們將注冊功能放入此工程
(1)添加web.xml
(2)引入依賴pinyougou-user-interface 、spring相關(guān)依賴(參照其它web工程),tomcat運行端口9106
(3)添加spring配置文件
(4)拷貝靜態(tài)原型頁面register.html 及相關(guān)資源
4.3基本注冊功能實現(xiàn)
4.3.1生成和拷貝代碼
4.3.2后端服務(wù)實現(xiàn)層
修改pinyougou-user-service的UserServiceImpl.java
/** * 增加 */ @Override public void add(TbUser user) { user.setCreated(new Date());//創(chuàng)建日期 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=”設(shè)置登錄密碼” 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>同意協(xié)議并注冊《品優(yōu)購用戶協(xié)議》</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實現(xiàn)思路
點擊頁面上的”獲取短信驗證碼”連接,向后端傳遞手機號。后端隨機生成6位數(shù)字作為短信驗證碼,將其保存在redis中(手機號作為KEY),并發(fā)送到短信網(wǎng)關(guān)。
用戶注冊時,后端根據(jù)手機號查詢redis中的驗證碼與用戶填寫的驗證碼是否相同,如果不同則提示用戶不能注冊。
4.4.2生成驗證碼
(1)修改pinyougou-user-interface工程UserService.java ,增加方法
/** * 生成短信驗證碼 * @return */ public void createSmsCode(String phone);
(2)修改pinyougou-user-service工程的UserServiceImpl.java
@Autowired private RedisTemplate<String , Object> redisTemplate; /** * 生成短信驗證碼 */ public void createSmsCode(String phone){ //生成6位隨機數(shù) String code = (long) (Math.random()*1000000) “”; System.out.println(“驗證碼:” code); //存入緩存 redisTemplate.boundHashOps(“smscode”).put(phone, code); //發(fā)送到activeMQ …. }
(3)在 pinyougou-common 添加工具類PhoneFormatCheckUtils.java,用于驗證手機號
(4)修改pinyougou-user-web的UserController.java
/** * 發(fā)送短信驗證碼 * @param phone * @return */ @RequestMapping(“/sendCode”) public Result sendCode(String phone){ //判斷手機號格式 if(!PhoneFormatCheckUtils.isPhoneLegal(phone)){ return new Result(false, “手機號格式不正確”); } try { userService.createSmsCode(phone);//生成驗證碼 return new Result(true, “驗證碼發(fā)送成功”); } catch (Exception e) { e.printStackTrace(); return new Result(true, “驗證碼發(fā)送失敗”); } }
(5)pinyougou-user-web的userService.js
//發(fā)送驗證碼 this.sendCode=function(phone){ return $http.get(“../user/sendCode.do?phone=” phone); }
(6)pinyougou-user-web的userController.js
//發(fā)送驗證碼 $scope.sendCode=function(){ if($scope.entity.phone==null){ alert(“請輸入手機號!”); return ; } userService.sendCode($scope.entity.phone).success( function(response){ alert(response.message); } ); }
(7)修改頁面register.html
<a ng-click=”sendCode()” >獲取短信驗證碼</a>
4.4.3用戶注冊判斷驗證碼
(1)修改pinyougou-user-interface的UserService.java
/** * 判斷短信驗證碼是否存在 * @param phone * @return */ 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
/** * 增加 * @param user * @return */ @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, “增加失敗”); } }
(4)修改pinyougou-user-web的userService.js
//增加 this.add=function(entity,smscode){ return $http.post(‘../user/add.do?smscode=’ smscode ,entity ); }
(5)修改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短信驗證碼發(fā)送到手機
(1)在pinyougou-user-service添加配置文件applicationContext-activemq.xml
<!– 真正可以產(chǎn)生Connection的ConnectionFactory,由對應(yīng)的 JMS服務(wù)廠商提供–> <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”> <!– 目標(biāo)ConnectionFactory對應(yīng)真實的可以產(chǎn)生JMS Connection的ConnectionFactory –> <property name=”targetConnectionFactory” ref=”targetConnectionFactory”/> </bean> <!– Spring提供的JMS工具類,它可以進行消息發(fā)送、接收等 –> <bean id=”jmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <!– 這個connectionFactory對應(yīng)的是我們定義的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位隨機數(shù) final String code = (long) (Math.random()*1000000) “”; System.out.println(“驗證碼:” code); //存入緩存 redisTemplate.boundHashOps(“smscode”).put(phone, code); //發(fā)送到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));//參數(shù) return mapMessage; } }); }
(3)在pinyougou-common的properties目錄下創(chuàng)建配置文件sms.properties
template_code=SMS_85735065sign_name=u9ED1u9A6C