本篇本章是發送短信的第一部分, 說一下同步/異步發送短信的代碼, 以后幾篇我們稍微完善一下功能, 添加發送頻率的限制和日發送次數的限制.
發送短信的方法可能不少, 我們的方法是使用服務商提供的服務. 一般來說, 這些服務都是和語言無關的, 這里我們使用java寫示例程序.
1、發送短信的接口
根據自己的情況選擇服務商。
2、開發文檔
從開發文檔中我們可以看到. 可以直接使用http請求也可以使用WebService請求發送短信. 由于DEMO文件夾下的java和jsp文件夾中的代碼都是使用http請求發送短信. 所以這里就不再細說了, 我們使用WebService的方式演示發送短信.
3、生成客戶端代碼
從接口文檔中我們知道它的WebService的WSDL的url為: http://106.ihuyi.cn/webservice/sms.php?WSDL 那么我們可以執行下面的命令生成客戶端代碼:
1
|
wsimport -keep http: //106.ihuyi.cn/webservice/sms.php?WSDL |
其中wsimport是JDK自帶的工具, -keep url選項是"保留生成的文件". 該命令會在當前目錄下生成sms.cn.ihuyi._106包, 以及眾多的類. 接下來開始編寫我們自己的代碼.
4、定義接口
為了方便, 這里我們首先定義一個接口:
Sms.java
1
2
3
4
5
6
7
8
9
10
|
public interface Sms { /** * 向mobile發送短信, 內容為message * * @param mobile 手機號 * @param message 短信內容 * @return 成功返回-1, 否則返回其他值 */ int sendMessage(String mobile, String message); } |
這個接口很簡單, 只有一個方法. 這個方法用來發送短信.
5、同步發送短信
接下來我們首先實現一個同步發送短信的類:
IhuyiSmsImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class IhuyiSmsImpl implements Sms { private String account; private String password; public void setAccount(String account) { this .account = account; } public void setPassword(String password) { this .password = password; } @Override public int sendMessage(String mobile, String message) { cn.ihuyi._106.Sms factory = new cn.ihuyi._106.Sms(); SmsSoap smsSoap = factory.getSmsSoap(); SubmitResult submit = smsSoap.submit(account, password, mobile, message); int code = submit.getCode(); if (code == 2 ){ return - 1 ; } System.out.println( "發送短信失敗, code:" + code); return code; } } |
在第17行, 我們獲得遠程對象的一個代理對象. 之后就可以通過這個代理對象進行發送短信, 查詢賬戶余額等操作.
第18行, 使用該代理對象的submit方法提交了短信內容. 該方法的參數信息及返回值含義在接口文檔中有詳細的說明.
第19行我們獲得了結果的狀態碼. 根據文檔上的說明, 狀態碼為2說明提交成功. 簡單起見, 這里我們只關注提交成功的情況. 需要注意的是, 狀態碼為2只是說明提交成功. 根據官網上的"3-5秒內響應、100%到達", 我們可以推測. 如果提交成功, 那么基本上3-5秒內,短信就會發送成功, 根據用戶的網絡情況, 可能稍有延遲用戶就可以收到短信.
使用這段代碼發送短信也很簡單, 直接new一個對象, 設置好賬號和密碼就可以發送短信了.
6、異步發送短信
由于發送短信涉及到網絡通信, 因此sendMessage方法可能會有一些延遲. 為了改善用戶體驗, 我們可以使用異步發送短信的方法. 原理很簡單: 如果用戶請求發送短信, 我們不是直接調用IhuyiSmsImpl的sendMessage方法, 而是將請求保存起來(生產者), 然后告訴用戶: 短信發送成功. 之后有若干個消費者取出任務, 調用sendMessage方法發送短信.
這里, 我使用線程池完成上面的任務:
AsyncSmsImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public class AsyncSmsImpl implements Sms { public Sms sendSms; private ExecutorService executorService = Executors.newFixedThreadPool( 3 ); public void setSendSms(Sms sendSms) { this .sendSms = sendSms; } @Override public int sendMessage(String mobile, String message) { try { executorService.submit(() -> sendSms.sendMessage(mobile, message)); } catch (Exception e) { Sysemt.out.println( "提交任務時發生錯誤" + e); return 0 ; } return - 1 ; } public void destroy(){ try { executorService.shutdown(); } catch (Exception e){} } } |
代碼很簡單, 直接將Sms接口的sendMessage(mobile, message)方法作為一個任務加到線程池的任務隊列中. 這樣等到有空閑線程時, 就會執行sendSms.sendMessage(mobile, message)發送短信. 這里我們假設只要保存到線程池就可以成功發送短信. 因為發送失敗的情況實際上很罕見.
到這里同步/異步發送短信就算是完成了, 接下來的幾篇我們看看一些常見的限制的實現, 比如: 一分鐘只能發1次, 一天只能發送5次等.
希望大家喜歡這篇文章。