首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

SmsLib 短信貓 Java 開發包整合指南與常見問題排查

     編輯:Java 綜合教學

基於 SmsLib 實現串口短信發送:環境配置、代碼實戰與避坑指南

在物聯網、工業監控、金融通知等場景,通過短信貓(GSM/GPRS Modem)直發短信具有「不依賴互聯網、到達率高、成本可控」的優勢。SmsLib v3.x 是 Java 生態中最成熟的短信貓開發庫。本文詳述 Maven 依賴管理、原生庫加載、核心 API 調用、編碼處理及高頻故障排查。

一、 環境依賴與原生庫部署(關鍵步驟)

SmsLib 依賴 JavaComm (javax.comm) 訪問串口,涉及 JNI 原生庫,部署極易出錯。

1. Maven 依賴 (中央倉庫無 v3.3.0,需手動安裝或使用 JitPack)

<!-- 建議使用維護分支 fork 版本 -->
<dependency>
    <groupId>org.smslib</groupId>
    <artifactId>smslib</artifactId>
    <version>3.5.4</version> <!-- 或 3.3.0 歷史版本 -->
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<!-- JavaComm 官方無 Maven 坐標,需 system scope 引用本地 jar -->
<dependency>
    <groupId>javax.comm</groupId>
    <artifactId>comm</artifactId>
    <version>2.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/comm.jar</systemPath>
</dependency>

2. 原生庫文件放置位置(路徑錯誤是 90% 問題根因)

文件目標目錄說明
javax.comm.properties%JAVA_HOME%/jre/lib/指定驅動類 com.sun.comm.Win32Driver
win32com.dll%JAVA_HOME%/jre/bin/Windows 串口 JNI 庫(32/64 位必須與 JDK 一致)
comm.jar%JAVA_HOME%/jre/lib/ext/擴展類加載器加載,確保 javax.comm 可見

⚠️ 關鍵驗證:啟動 JDK 自帶 java -jar comm.jar 或編寫測試代碼 CommPortIdentifier.getPortIdentifiers() 能枚舉到 COM 口,才說明環境就緒。

3. JDK 版本陷阱

  • SmsLib 3.x / JavaComm 2.0 僅支持 32 位 JDK 1.5~1.7。
  • JDK 1.8+ 移除了 jre/lib/ext 機制,需用 -Djava.ext.dirs 或模塊化方案(極其麻煩)。
  • 強烈建議:使用 32 位 JDK 1.7 (jdk-1_5_0_04 或 jdk1.7.0_80) 運行該模塊,或遷移至 jSerialComm (純 Java 無原生庫、支持 JDK 8~21、跨平台)。

二、 核心發送代碼實現

package com.alonely.notecat;

import org.smslib.*;
import org.smslib.modem.SerialModemGateway;

public class SendMessage {

    // 異步發送結果回調
    private static class OutboundNotification implements IOutboundMessageNotification {
        @Override
        public void process(String gatewayId, OutboundMessage msg) {
            System.out.println("【發送回調】Gateway: " + gatewayId + " | Msg: " + msg);
        }
    }

    @SuppressWarnings("deprecation")
    public void sendSMS(String mobilePhones, String content) {
        Service srv = null;
        try {
            srv = Service.getInstance();
            
            // 配置串口網關
            SerialModemGateway gateway = new SerialModemGateway(
                "modem.com3",   // 網關 ID
                "COM3",         // 串口號 (Windows: COM1~COM9, Linux: /dev/ttyUSB0)
                9600,           // 波特率 (短信貓默認 9600/115200)
                "wavecom",      // 製造商 (可為空)
                ""              // 型號 (可為空)
            );
            
            gateway.setInbound(true);   // 接收短信
            gateway.setOutbound(true);  // 發送短信
            gateway.setSimPin("0000");  // SIM 卡 PIN 碼 (無則空字符串)
            gateway.setOutboundNotification(new OutboundNotification());
            
            srv.addGateway(gateway);
            System.out.println("初始化成功,啟動服務...");
            srv.startService();
            System.out.println("服務啟動成功");

            // 批量發送
            String[] phones = mobilePhones.split(",");
            for (String phone : phones) {
                OutboundMessage msg = new OutboundMessage(phone.trim(), content);
                msg.setEncoding(Message.MessageEncodings.ENCUCS2); // 中文必須 UCS2 (Unicode)
                srv.sendMessage(msg);
                System.out.println("已發送至: " + phone);
                Thread.sleep(500); // 避免發送過快導致模組緩衝區溢出
            }
        } catch (Exception e) {
            System.err.println("發送異常: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if (srv != null) {
                try { srv.stopService(); } catch (Exception ignored) {}
            }
        }
    }

    public static void main(String[] args) {
        new SendMessage().sendSMS("13800138000,13900139000", "【測試】Java SmsLib 短信發送成功!");
    }
}

三、 中文編碼與 PDU 模式深度解析

編碼模式SmsLib 常量適用場景單條字符數限制
GSM 7-bit 默認字母表ENC7BIT純英文/數字/少量符號160 字符
8-bit 數據ENC8BIT二進制數據、WAP Push140 字節
UCS-2 (UTF-16BE)ENCUCS2中文/多語言/Emoji70 字符 (超過自動拆分長短信)

長短信拆分:SmsLib 內部自動處理 Concatenated SMS (UDH 頭部),發送端無感知,接收端手機自動重組。

四、 高頻故障排查手冊

錯誤現象根因分析解決方案
NoClassDefFoundError: org/apache/log4j/Logger缺少 log4j JAR加入 log4j-1.2.17.jar 到 classpath
NoSuchPortException / PortInUseException1. 串口號錯誤 2. 被其他程序佔用 3. JDK 位數不匹配 (64位 JDK 載入 32位 dll)1. 設備管理器確認 COM 口號 2. 關閉串口調試助手/其他占用程序 3. 強制使用 32位 JDK
GatewayException: Comm library exceptionjavax.comm 原生庫加載失敗檢查 win32com.dll 是否在 jre/bin,comm.jar 是否在 jre/lib/ext,javax.comm.properties 配置正確
發送成功但手機收不到1. SIM 卡欠費/無信號 2. 短信中心號碼 (SMSC) 未設置 3. 運行營商攔截1. 手機測試 SIM 卡 2. AT 指令設置 SMSC: AT+CSCA="+8613800755500" 3. 換卡/換號段測試
中文顯示亂碼/問號未設置 UCS2 編碼msg.setEncoding(MessageEncodings.ENCUCS2)
Eclipse 運行正常,打包 JAR 失效原生庫未隨 JAR 發布,系統路徑依賴打包時排除 comm.jar/win32com.dll,部署腳本手動佈署到目標機器 JRE 目錄

五、 現代化替代方案:jSerialComm (強烈推薦)

SmsLib + JavaComm 技術棧已停維護超 10 年,jSerialComm 是純 Java 實現、無原生庫依賴、支持 JDK 8~21、跨平台(Win/Linux/macOS/ARM)的現代串口庫。

<dependency>
    <groupId>com.fazecast</groupId>
    <artifactId>jSerialComm</artifactId>
    <version>2.10.4</version>
</dependency>

// 簡單發送 AT 指令示例
SerialPort port = SerialPort.getCommPort("COM3");
port.setBaudRate(9600);
port.openPort();
try (OutputStream out = port.getOutputStream();
     BufferedReader in = new BufferedReader(new InputStreamReader(port.getInputStream()))) {
    // 設置 PDU 模式
    out.write("AT+CMGF=0\r\n".getBytes()); out.flush(); Thread.sleep(500);
    // 發送 PDU 封裝後的短信 (需自行實現 PDU 編碼或引入 smslib 核心編碼邏輯)
    // ...
} finally { port.closePort(); }

六、 生產環境部署清單

  1. ✅ 專用 32 位 JDK 1.7 運行短信模塊(獨立進程/微服務)
  2. ✅ 短信貓供電穩定(獨立供電適配器,避免 USB 供電不足掉線)
  3. ✅ 串口線屏蔽良好,遠離強電/變頻器干擾源
  4. ✅ 監控:發送成功率、佇列積壓、Modem 信號強度 (AT+CSQ)、SIM 卡餘額
  5. ✅ 熔斷:連續 5 次發送失敗自動熔斷,告警運維介入
  6. ✅ 幂等:業務層去重,防止重試導致重複發送
  7. ✅ 合規:內容模板審核、發送頻率限制(運商反垃圾規則)、退訂機制

短信貓直發雖然技術棧老舊,但在特定場景下不可替代。掌握 JavaComm 環境配置核心邏輯、PDU 編碼原理、以及向 jSerialComm 遷移的路徑,能讓你在維護舊系統與構建新系統時游刃有餘。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved