淺析如何在Java應(yīng)用中優(yōu)雅的發(fā)送短信
這篇文章,我們聊聊 Java 應(yīng)用中如何優(yōu)雅的發(fā)送短信。

1 客戶端/服務(wù)端兩種模式
Java 應(yīng)用中發(fā)送短信通常需要使用短信服務(wù)提供商提供的短信 API 。
我們經(jīng)常使用的短信渠道有:阿里云、騰訊云、華為云、億美等。
發(fā)送短信模式分為兩種:
1、客戶端模式
客戶端模式是指應(yīng)用系統(tǒng)直接調(diào)用短信服務(wù)提供商提供的短信 API 發(fā)送短信。

2、服務(wù)端模式
服務(wù)端模式是獨(dú)立創(chuàng)建一個(gè)短信平臺(tái)服務(wù),應(yīng)用系統(tǒng)直接使用短信平臺(tái)服務(wù)提供的 SDK 發(fā)送短信。

核心流程如下:
- 前端調(diào)用應(yīng)用服務(wù)接口發(fā)送短信 ;
- 應(yīng)用服務(wù)收到短信請(qǐng)求后,調(diào)用 SDK 方法根據(jù)模版發(fā)送短信;
- 短信平臺(tái)服務(wù)收到請(qǐng)求,根據(jù)路由算法選擇配置的渠道(比如阿里云、騰訊云)發(fā)送短信;
- 短信成功發(fā)送到用戶手機(jī) 。
2 客戶端模式
1、使用三方短信渠道 SDK
客戶端模式是非常簡(jiǎn)單的模式,很多短信服務(wù)提供商會(huì)提供成熟的 SDK ,業(yè)務(wù)系統(tǒng)只需要添加 SDK 依賴以及相關(guān)配置,就可以調(diào)用 SDK 提供的方法發(fā)送短信。
我們以阿里云短信服務(wù)為例, 調(diào)用 API 發(fā)送短信的全流程如下所示:

使用 SDK 示例如下:

國(guó)內(nèi)云廠商阿里云、騰訊云、華為云的短信服務(wù),都需要依次申請(qǐng)簽名,申請(qǐng)模版,審核通過(guò)之后才能發(fā)送短信。
2、封裝多個(gè)三方渠道接口
雖然使用三方短信渠道 SDK 非常簡(jiǎn)單,但是在實(shí)際項(xiàng)目中,可能會(huì)存在多個(gè)三方渠道,也就是說(shuō):可能有的短信是通過(guò)騰訊云發(fā)送,有的是通過(guò)阿里云發(fā)送。 這樣就需要在工程中配置不同渠道的 SDK 依賴。
但這種方式會(huì)有兩個(gè)明顯的問(wèn)題 :
- 不同渠道的發(fā)送短信代碼不一致,業(yè)務(wù)代碼偏混亂。
- 工程中引入到 SDK 包比較多,不同的 SDK 依賴并不相同,可能存在沖突問(wèn)題 。
為了解決這個(gè)問(wèn)題,有一種方法是擯棄三方渠道 SDK ,自己實(shí)現(xiàn) SDK 的發(fā)送短信方法,這樣可以統(tǒng)一發(fā)送短信代碼,易于管理。
筆者發(fā)現(xiàn)一個(gè)開(kāi)源項(xiàng)目 SMS4J,該項(xiàng)目為短信聚合框架,旨在集成多家短信服務(wù),解決接入多個(gè)短信 SDK 的繁瑣流程。

下面我們展示在 SpringBoot 環(huán)境如何集成。
- maven 引入
<dependency> <groupId>org.dromara.sms4j</groupId> <artifactId>sms4j-spring-boot-starter</artifactId> <version>3.0.2</version> </dependency>
- 設(shè)置配置文件
sms:
alibaba:
#阿里云的accessKey
accessKeyId: 您的accessKey
#阿里云的accessKeySecret
accessKeySecret: 您的accessKeySecret
#短信簽名
signature: 測(cè)試簽名
#模板ID 用于發(fā)送固定模板短信使用
templateId: SMS_215125134
#模板變量 上述模板的變量
templateName: code
#請(qǐng)求地址 默認(rèn)為dysmsapi.aliyuncs.com 如無(wú)特殊改變可以不用設(shè)置
requestUrl: dysmsapi.aliyuncs.com
huawei:
#華為短信appKey
appKey: 5N6fvXXXX920HaWhVXXXXXX7fYa
#華為短信appSecret
app-secret: Wujt7EYzZTBXXXXXXEhSP6XXXX
#短信簽名
signature: 華為短信測(cè)試
#通道號(hào)
sender: 8823040504797
#模板ID 如果使用自定義模板發(fā)送方法可不設(shè)定
template-id: acXXXXXXXXc274b2a8263479b954c1ab5
#華為回調(diào)地址,如不需要可不設(shè)置或?yàn)榭?
statusCallBack:
#華為分配的app請(qǐng)求地址
url: https://XXXXX.cn-north-4.XXXXXXXX.com:443
zhutong:
#助通短信
#助通終端用戶管理的用戶名 username 必填;非登錄賬號(hào)密碼,請(qǐng)登錄后臺(tái)管理地址進(jìn)行查看:http://mix2.zthysms.com/login
accessKeyId: tushu1122XXX
#助通終端用戶管理的用戶名 passwrod 必填;
accessKeySecret: UbXXX4SL
#短信簽名,可選;可選的時(shí)候,只能使用自定義短信不能使用模板短信; 具體在這里查看審核過(guò)的短信簽名:https://mix2.zthysms.com/index.html#/SignatureManagement
signature: 上海千XXXX
- 方法使用
@RestController
@RequestMapping("/test/")
public class DemoController {
// 測(cè)試發(fā)送固定模板短信
@RequestMapping("/")
public void doLogin(String username, String password) {
//阿里云向此手機(jī)號(hào)發(fā)送短信
SmsFactory.createSmsBlend(SupplierType.ALIBABA).
sendMessage("18888888888","123456");
//華為短信向此手機(jī)號(hào)發(fā)送短信
SmsFactory.createSmsBlend(SupplierType.HUAWEI).
sendMessage("16666666666","000000");
}
}
客戶端模式是簡(jiǎn)單實(shí)用的模式,我們可以直接引入三方渠道的 SDK 發(fā)送短信,但當(dāng)存在多種渠道短信時(shí),可能代碼會(huì)比較混亂。
雖然我們可以封裝多個(gè)三方渠道接口來(lái)解決問(wèn)題,但研發(fā)成本還是比較高的。
另外,當(dāng)研發(fā)小組分散,發(fā)送短信各自自成體系時(shí),當(dāng)某一個(gè)渠道由于某種原因被棄用時(shí),大部分研發(fā)小組都可能會(huì)受影響。
3 服務(wù)端模式
服務(wù)端模式是獨(dú)立創(chuàng)建一個(gè)短信平臺(tái)服務(wù),應(yīng)用服務(wù)直接使用短信平臺(tái)提供的 SDK 發(fā)送短信。
短信平臺(tái)的設(shè)計(jì)有如下要點(diǎn):
1、應(yīng)用管理
短信平臺(tái)為每一個(gè)接入的應(yīng)用分配單獨(dú)的 appKey 和 appSecret ,每一個(gè)應(yīng)用可以配置獨(dú)立的限流策略。
2、精簡(jiǎn)的 SDK 提供按照模版單發(fā)/群發(fā)的功能
public SmsSenderResult sendSmsByTemplateId(
String mobile,
String templateId,
Map<String, String> templateParam);
3、簽名、模版管理
每個(gè)應(yīng)用服務(wù)涉及到的簽名、模版的管理都中心化 ,我們可以讓一個(gè)模板綁定多個(gè)渠道。
當(dāng)某條短信通過(guò)渠道 A 發(fā)送失敗時(shí),可以通過(guò)另一個(gè)渠道 B 發(fā)送,如此可以達(dá)到高可用的效果。
4、多渠道適配
服務(wù)端要加載多個(gè)渠道的 SDK ,那么可能導(dǎo)致依賴沖突,可以采取 SPI 機(jī)加載渠道插件。
筆者曾經(jīng)重構(gòu)過(guò)一個(gè)短信平臺(tái)服務(wù),架構(gòu)圖如下:

- 模仿騰訊云的 SDK 設(shè)計(jì),提供簡(jiǎn)單易用的短信接口;
- 設(shè)計(jì)短信服務(wù) API 端,接收發(fā)短信請(qǐng)求,發(fā)送短信信息到消息隊(duì)列;
- worker 服務(wù)消費(fèi)消息,按照負(fù)載均衡的算法,調(diào)用不同渠道商的短信接口;
- Dashboard 可以查看短信發(fā)送記錄,配置渠道商信息。
以上就是淺析如何在Java應(yīng)用中優(yōu)雅的發(fā)送短信的詳細(xì)內(nèi)容,更多關(guān)于Java應(yīng)用中發(fā)送短信的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JAVA中String類與StringBuffer類的區(qū)別
這篇文章主要為大家詳細(xì)介紹了JAVA中String類與StringBuffer類的區(qū)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
SpringBoot中使用spring-retry 解決失敗重試調(diào)用
本文主要介紹了SpringBoot中使用spring-retry 解決失敗重試調(diào)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
JDK1.7 Paths,Files類實(shí)現(xiàn)文件夾的復(fù)制與刪除的實(shí)例
下面小編就為大家分享一篇JDK1.7 Paths,Files類實(shí)現(xiàn)文件夾的復(fù)制與刪除的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。以前跟隨小編過(guò)來(lái)看看吧2017-11-11
解決子線程無(wú)法訪問(wèn)父線程中通過(guò)ThreadLocal設(shè)置的變量問(wèn)題
這篇文章主要介紹了解決子線程無(wú)法訪問(wèn)父線程中通過(guò)ThreadLocal設(shè)置的變量問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
關(guān)于Java實(shí)現(xiàn)word(docx、doc)轉(zhuǎn)html的完美解決方案
文章介紹了多種將Word文檔轉(zhuǎn)換為HTML的方法,包括使用Microsoft Word自帶的導(dǎo)出功能、第三方工具和編程實(shí)現(xiàn),展示了如何實(shí)現(xiàn)將.docx文件轉(zhuǎn)換為HTML文件,并自動(dòng)生成目錄、處理分頁(yè)符和增強(qiáng)表格樣式等功能,感興趣的朋友一起看看吧2025-01-01
SpringCloud Gateway跨域配置代碼實(shí)例
這篇文章主要介紹了SpringCloud Gateway跨域配置代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringBoot MockMvc單元測(cè)試的示例代碼
這篇文章主要介紹了SpringBoot MockMvc單元測(cè)試的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼
這篇文章主要介紹了Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07

