簡訊發送涉及網路 I/O,同步呼叫會阻塞主執行緒,影響使用者體驗。本文從服務商介接、WSDL 產生客戶端代碼開始,逐步建立統一介面,實作同步發送與基於執行緒池的非同步發送,程式碼簡潔可直接用於生產環境。
Sms 介面
├─ IhuyiSmsImpl // 同步實作,呼叫 WebService
└─ AsyncSmsImpl // 非同步包裝,委派給執行緒池
public interface Sms {
/** @return 成功回傳 -1,失敗回傳錯誤碼 */
int sendMessage(String mobile, String message);
}
public class IhuyiSmsImpl implements Sms {
private String account, password;
// setter 略
@Override
public int sendMessage(String mobile, String message) {
cn.ihuyi._106.Sms factory = new cn.ihuyi._106.Sms();
SmsSoap soap = factory.getSmsSoap();
SubmitResult result = soap.submit(account, password, mobile, message);
return (result.getCode() == 2) ? -1 : result.getCode(); // 2=提交成功
}
}
public class AsyncSmsImpl implements Sms {
private final Sms delegate;
private final ExecutorService pool = Executors.newFixedThreadPool(3);
public AsyncSmsImpl(Sms delegate) { this.delegate = delegate; }
@Override
public int sendMessage(String mobile, String message) {
try {
pool.submit(() -> delegate.sendMessage(mobile, message));
return -1; // 假設入隊即成功
} catch (Exception e) {
System.err.println("提交任務失敗: " + e);
return 0;
}
}
public void destroy() { pool.shutdown(); }
}
// 同步
Sms sync = new IhuyiSmsImpl();
sync.setAccount("xxx"); sync.setPassword("yyy");
sync.sendMessage("13800000000", "驗證碼:123456");
// 非同步(Spring 管理生命週期時呼叫 destroy())
Sms async = new AsyncSmsImpl(new IhuyiSmsImpl());
async.sendMessage("13800000000", "驗證碼:123456"); // 立即返回,背景發送
下一篇將加入「頻率限制」(每分鐘 1 通)、「每日發送上限」(每日 5 通)等實務管控功能,敬請期待。