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

J2ME 網絡編程完全指南:Generic Connection Framework、HttpConnection 與貨幣匯率實戰案例

     編輯:Java 相關知識

J2ME 網絡架構概覽

Java 2 Micro Edition (J2ME) 為資源受限的移動設備提供網絡能力。核心包:

  • javax.microedition.io — **Generic Connection Framework (GCF)**,統一連接接口
  • java.io — 精簡 I/O 流支持 (J2SE 子集)

GCF 核心接口體系

接口功能典型協議
InputConnection 基本串行輸入 文件、串口
OutputConnection 基本串行輸出 文件、串口
StreamConnection 流式雙向通信 TCP Socket (socket://)
StreamConnectionNotifier 服務端監聽 TCP Server Socket
DatagramConnection 無連接數據報 UDP (datagram://)
HttpConnection HTTP 客戶端 HTTP/HTTPS (https://, https://)
HttpsConnection HTTPS 安全連接 SSL/TLS over HTTP
SecureConnection 通用安全連接 SSL/TLS (ssl://)
CommConnection 串口通信 RS-232, Bluetooth (comm:)

Connector.open() 動態協議解析


// 核心工廠方法:根據 URL 協議前綴動態加載實現類
Connection conn = Connector.open(String url, int mode, boolean timeout);

// 支持的 URL 模式:
Connector.open("https://www.example.com");           // HTTP GET
Connector.open("socket://192.168.1.100:8080");      // TCP Client
Connector.open("socket://:9000");                   // TCP Server (監聽)
Connector.open("datagram://:1234");                 // UDP 接收
Connector.open("datagram://10.0.0.1:1234");         // UDP 發送
Connector.open("comm:0;baudrate=9600");             // 串口
Connector.open("file:///data/config.txt");          // 文件 I/O
Connector.open("https://secure.example.com");       // HTTPS
Connector.open("ssl://host:443");                   // 原始 SSL

HTTP 連接生命周期與數據處理

三階段狀態機:
┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   Setup     │────▶│  Connected   │────▶│   Closed    │
│  (準備請求)  │     │ (發送/接收)   │     │  (關閉釋放)  │
└─────────────┘     └──────────────┘     └─────────────┘
      │                    │                    │
      ▼                    ▼                    ▼
open()              openInputStream()        close()
setRequestMethod()  openOutputStream()       
setRequestProperty() read()/write()          

標準 HTTP 請求代碼模板

String getViaHttpConnection(String url) throws IOException {
    HttpConnection conn = null;
    InputStream is = null;
    StringBuffer response = new StringBuffer();
    
    try {
        // 1. 建立連接 (Setup 階段)
        conn = (HttpConnection) Connector.open(url);
        
        // 2. 可選:設置請求屬性
        conn.setRequestMethod(HttpConnection.GET);
        conn.setRequestProperty("User-Agent", "J2ME-Agent/1.0");
        conn.setRequestProperty("Accept", "text/html");
        
        // 3. 獲取輸入流 → 自動發送請求、接收響應頭
        is = conn.openInputStream();
        
        // 4. 讀取響應體
        int ch;
        while ((ch = is.read()) != -1) {
            response.append((char) ch);
        }
        
        // 5. 可選:獲取響應信息
        int status = conn.getResponseCode();  // HTTP 狀態碼
        String type = conn.getType();         // Content-Type
        long len = conn.getLength();          // Content-Length
        
    } finally {
        // 6. 必須關閉資源 (順序重要)
        if (is != null) is.close();
        if (conn != null) conn.close();
    }
    
    return response.toString();
}

實戰案例:貨幣匯率查詢 MIDlet

需求分析

  • 目標:獲取 USD/GBP 即時匯率
  • 數據源:Yahoo Finance API (示例 URL: https://finance.yahoo.com/m5?a=1&s=USD&t=GBP)
  • 挑戰:移動設備無瀏覽器渲染 HTML,需客戶端解析 HTML 字符串

核心解析邏輯

// 從 HTML 中提取匯率: 搜索 "USDGBP" 模式,定位小數點,提取數字
String parseRate(String html) {
    String rate = "";
    int idx = html.indexOf("USDGBP");
    if (idx != -1) {
        html = html.substring(idx);
        int dot = html.indexOf(".");
        if (dot != -1 && !html.endsWith(".") && Character.isDigit(html.charAt(dot+1))) {
            // 向前提取整數部分
            String front = "";
            for (int i = dot-1; i >= 0 && Character.isDigit(html.charAt(i)); i--) {
                front = html.charAt(i) + front;
            }
            // 向後提取小數部分 (取 2-4 位)
            String back = "";
            for (int i = dot+1; i < html.length() && Character.isDigit(html.charAt(i)) && back.length() < 4; i++) {
                back += html.charAt(i);
            }
            rate = front + "." + back;
        }
    }
    return rate;
}

// 提取相關信息 (如市場狀態、時間)
String parseMeta(String html) {
    String meta = "";
    int idx = html.indexOf("U.S. Markets Closed.");
    if (idx != -1) {
        // 向前取 34 字符作為時間戳
        meta = html.substring(Math.max(0, idx-34), idx) + " U.S. Markets Closed";
    }
    return meta;
}

完整 MIDlet 代碼結構

public class CurrencyExchange extends MIDlet implements CommandListener {
    private Display display;
    private Form form;
    private Command exitCmd;
    
    public CurrencyExchange() {
        display = Display.getDisplay(this);
        exitCmd = new Command("Exit", Command.SCREEN, 1);
    }
    
    protected void startApp() {
        form = new Form("Exchange Rate");
        form.addCommand(exitCmd);
        form.setCommandListener(this);
        
        // 異步執行網絡請求 (避免阻塞 UI 線程)
        new Thread(() -> {
            try {
                String url = "https://finance.yahoo.com/m5?a=1&s=USD&t=GBP";
                String html = getViaHttpConnection(url);
                String rate = parseRate(html);
                String meta = parseMeta(html);
                String result = "USD/GBP " + rate + " at " + meta;
                
                // 回到事件線程更新 UI
                Display.getDisplay(this).callSerially(() -> 
                    form.append(result)
                );
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
        
        display.setCurrent(form);
    }
    
    protected void pauseApp() {}
    protected void destroyApp(boolean unconditional) {}
    
    public void commandAction(Command c, Displayable d) {
        if (c == exitCmd) {
            destroyApp(false);
            notifyDestroyed();
        }
    }
    
    // ... getViaHttpConnection, parseRate, parseMeta 方法
}

關鍵技術難點與解決方案

挑戰J2ME 限制解決方案
內存極小 (100KB-1MB) 不能載入完整 DOM 解析器 流式讀取 + 字符串索引解析,不構建對象樹
無多線程保障 部分實現單線程 網絡操作放獨立線程,UI 更新用 callSerially()
連接不穩定 移動網絡高延遲、易斷 設置超時、重試邏輯、異常捕獲
安全限制 未簽名 MIDlet 不能聯網 簽名部署、權限聲明 (MIDlet-Permissions)
字符編碼 默認 ISO-8859-1 手動處理 UTF-8: new String(bytes, "UTF-8")

安全聯網:HTTPS 與證書管理


// HTTPS 連接
HttpsConnection conn = (HttpsConnection) Connector.open("https://api.example.com/data");

// 證書驗證 (設備內置根證書庫)
// 若服務器使用自簽名證書,需:
// 1. 獲取 SecurityInfo
SecurityInfo info = conn.getSecurityInfo();
// 2. 獲取證書鏈
Certificate[] certs = info.getServerCertificates();
// 3. 手動驗證或提示用戶信任
// 注意:無法動態添加根證書到設備信任庫

現代視角:J2ME 的歷史地位與繼承者

  • J2ME (CLDC/MIDP):2000-2010 統治功能機時代,諾基亞 S40、索愛、摩托羅拉主流
  • Android:2008 年發布,基於 Linux 內核 + Dalvik/ART VM,API 豐富度遠超 J2ME
  • Java ME Embedded 8+:Oracle 維護,面向 IoT 設備,支持模組化、現代安全協議
  • MicroEJ:商用 Java 虛擬機,運行在裸機/RTOS 上,兼容 Java 8 語法

總結

J2ME 的 Generic Connection Framework 是嵌入式 Java 網絡編程的經典設計:統一接口、協議無關、工廠模式動態綁定。雖然智能機時代已結束 J2ME 統治,但其設計思想在 Java ME Embedded、Android NDK 網絡層、IoT 輕量級協議棧 中仍有回響。掌握 Connector.open()、HttpConnection、流式解析、資源管理模式,對理解受限環境下的網絡編程極有價值。

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