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

J2ME 調用 Web Service 實戰:JSR 172 (JAX-RPC) 完整流程

     編輯:J2ME

背景

JSR 172 為 J2ME 提供 **JAX-RPC 子集** (Stub-based 調用) + **SAX/StAX 解析器**,支援 SOAP 1.1 over HTTP/HTTPS。需 MIDP 2.0 + CLDC 1.1 + 設備廠商實現 (WTK 2.2+ 內建,S60 3rd/FP1+ 真機支援)。

架構選型

方式優點缺點適用場景
JSR 172 Stub強類型、IDE 代碼生成、自動序列化JAR 體積大 (Stub+序列化器 ~50KB)、需 WSDL 預處理企業級應用、參數複雜、長期維護
手工 HTTP + KXML/NanoXML輕量、完全可控、無額外依賴手寫 SOAP 封包/解析易出錯、維護成本高簡單 RPC、極限 JAR 體積、無 JSR 172 設備
REST + JSON (手工)輕量、人類可讀、現代 API 風格需自行 JSON 解析 (org.json.me / kJSON)新項目首選、後端可控

JSR 172 完整流程 (以用戶登錄為例)

1. 獲取 WSDL

https://example.com/ws/auth?wsdl

2. 生成 Stub (WTK wscompile / Ant 任務)

wscompile -gen:client -d generated -classpath %WTK_HOME%\lib\j2mews.jar -f:wsi -features:documentliteral config.xml

config.xml 指定 WSDL 位置、包名、服務名。生成:AuthService_Stub、AuthServiceIF、序列化器類。

3. MIDlet 調用代碼

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.xml.rpc.*;
import java.rmi.*;
import generated.*;

public class WSLoginMidlet extends MIDlet implements CommandListener {
    private Display display;
    private Form form;
    private TextField tfUser, tfPass;
    private Command cmdLogin, cmdExit;
    private AuthServiceIF service;

    public WSLoginMidlet() {
        display = Display.getDisplay(this);
        form = new Form("WebService 登錄");
        tfUser = new TextField("用戶名", "", 20, TextField.ANY);
        tfPass = new TextField("密碼", "", 20, TextField.PASSWORD);
        cmdLogin = new Command("登錄", Command.OK, 1);
        cmdExit = new Command("退出", Command.EXIT, 1);
        form.append(tfUser); form.append(tfPass);
        form.addCommand(cmdLogin); form.addCommand(cmdExit);
        form.setCommandListener(this);

        // 初始化 Stub (耗時操作,放線程)
        new Thread(() -> {
            try {
                AuthService_Stub stub = new AuthService_Stub();
                stub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
                    "https://example.com/ws/auth");
                service = stub;
            } catch (Exception e) { e.printStackTrace(); }
        }).start();
    }

    protected void startApp() { display.setCurrent(form); }
    protected void pauseApp() {}
    protected void destroyApp(boolean u) {}

    public void commandAction(Command c, Displayable d) {
        if (c == cmdExit) { notifyDestroyed(); return; }
        if (c == cmdLogin) { new Thread(this::doLogin).start(); }
    }

    private void doLogin() {
        if (service == null) { showAlert("服務未就緒"); return; }
        try {
            String token = service.login(tfUser.getString(), tfPass.getString());
            // token 非空即成功
            showAlert("登錄成功", "Token: " + token);
        } catch (RemoteException e) {
            showAlert("網絡錯誤", e.getMessage());
        } catch (Exception e) {
            showAlert("異常", e.toString());
        }
    }

    private void showAlert(String title, String msg) {
        Alert a = new Alert(title, msg, null, AlertType.INFO);
        a.setTimeout(Alert.FOREVER);
        display.setCurrent(a, form);
    }
    private void showAlert(String msg) { showAlert("提示", msg); }
}

4. 打包與部署

  • 將生成的 generated/ 所有類複製進專案 src/。
  • 專案屬性 → API Selection → 勾選 J2ME Web Services (JSR 172)。
  • ProGuard 配置保留 Stub:-keep class generated.** { *; }。
  • 構建 JAD/JAR → OTA 部署真機測試。

常見坑點與對策

現象原因解決
Stub 初始化極慢 (5~10 秒)類載入 + 反射註冊序列化器啟動畫面顯示「正在連接服務...」,異步初始化
真機報 "UnsupportedContentType"伺服器返回非 text/xml (如 HTML 錯誤頁)檢查 Endpoint URL、伺服器日誌、防火牆/攔截器
JAR 體積超限 (> 64 KB/128 KB)Stub + 序列化器 + XML 解析器改用 REST+JSON (kJSON ~15KB) 或精簡 WSDL 僅保留必要操作
SSL 握手失敗設備無根證書/不支援 TLS 1.2HTTP 內網測試;生產需設備支援 JSSE (JSR 177 SATSA)

現代啟示

JSR 172 的 **Stub 生成、序列化映射、異步調用** 模式直接映射到現代:

  • Android: Retrofit + OkHttp + Moshi/Gson (介面定義 + 註解生成實現)
  • iOS: URLSession + Codable / Alamofire
  • 跨平台: gRPC (Protobuf) / GraphQL (Apollo) / tRPC

核心思想不變:**契約優先、代碼生成、類型安全、網絡細節封裝**。

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