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

Android 使用 HttpURLConnection 發送 Java 序列化對象實現雙端交互

     編輯:Java 綜合教學

Android 使用 HttpURLConnection 發送 Java 序列化對象實現雙端交互

利用 Java 原生序列化機制,配合 HttpURLConnection,實現 Android 客戶端與 Servlet 服務端的對象級雙向通訊。適合內部系統、簡單 RPC 场景。

核心前提

  • 雙端 **共享完全相同的實體類** (包名、類名、字段、serialVersionUID)
  • 實體類實現 java.io.Serializable
  • 設置請求頭 Content-Type: application/x-java-serialized-object

共享實體類 (dataPost.java)

package com.example.data; // 雙端包名必須一致!

public class dataPost implements Serializable {
    private static final long serialVersionUID = 1L; // 版本鎖定,防止反序列化失敗
    
    private String name;
    private String password;
    
    public dataPost(String name, String password) {
        this.name = name;
        this.password = password;
    }
    // Getter/Setter 省略
}

Android 客戶端發送與接收

public String sendDataByPost(String urlStr) {
    String result = "";
    try {
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        
        // 基礎配置
        conn.setConnectTimeout(2000);
        conn.setReadTimeout(2000);
        conn.setDoOutput(true);    // 允許寫出
        conn.setDoInput(true);     // 允許讀入
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        
        // 關鍵:聲明發送序列化對象
        conn.setRequestProperty("Content-Type", "application/x-java-serialized-object");
        
        // 構建對象輸出流
        ObjectOutputStream objOut = new ObjectOutputStream(conn.getOutputStream());
        
        // 發送對象
        dataPost data = new dataPost("Tom", null);
        objOut.writeObject(data);
        objOut.flush();
        objOut.close();
        
        // 讀取服務端返回對象
        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
            ObjectInputStream objIn = new ObjectInputStream(conn.getInputStream());
            dataPost response = (dataPost) objIn.readObject();
            result = response.getPassword(); // 獲取服務端設置的密碼
            objIn.close();
        } else {
            Log.w("HTTP", "連接失敗: " + conn.getResponseCode());
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

服務端 Servlet 處理

@WebServlet("/dataExchange")
public class DataExchangeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        // 1. 反序列化請求對象
        ObjectInputStream objIn = new ObjectInputStream(req.getInputStream());
        dataPost data = (dataPost) objIn.readObject();
        objIn.close();
        
        // 2. 業務處理
        data.setPassword("9964646"); // 模擬業務邏輯
        
        // 3. 序列化返回對象
        resp.setContentType("application/x-java-serialized-object");
        ObjectOutputStream objOut = new ObjectOutputStream(resp.getOutputStream());
        objOut.writeObject(data);
        objOut.flush();
        objOut.close();
    }
}

四大必踩坑與解決方案

坑點現象解決
URL 中文亂碼請求參數含中文導致 Server 解析異常URI uri = new URI(url, "utf-8"); url = uri.toString(); 進行編碼
主線程網絡請求崩潰NetworkOnMainThreadException**必須**在子線程/AsyncTask/RxJava/協程中執行網絡請求
包名不一致ClassNotFoundException: com.example.data.dataPost雙端 **完全相同包名**、類名、字段順序,建議提取為公共 Module/JAR
serialVersionUID 不匹配InvalidClassException: local class incompatible雙端**顯式聲明相同 serialVersionUID**,勿依賴編譯器自動生成

子線程調用範例

new Thread(() -> {
    String result = sendDataByPost("https://10.0.2.2:8080/server/dataExchange");
    runOnUiThread(() -> {
        if (!result.isEmpty()) {
            Log.i("HTTP", "服務端返回: " + result);
            // 更新 UI
        }
    });
}).start();

優缺點評估

優點缺點
零依賴,JDK 原生Java 序列化二進制格式不跨語言
對象圖完整傳遞 (含引用關係)序列化體積大、效能低、不安全 (反序列化漏洞)
代碼簡單,適合快速原型版本演進極難兼容 (增刪字段易破壞)

生產環境替代方案建議

  1. JSON + HTTP: Gson/Jackson + OkHttp/Retrofit,跨語言、可讀、生態成熟
  2. Protocol Buffers: 高效二進制、強 Schema、多語言、向後兼容
  3. gRPC: 基於 Protobuf 的 RPC 框架,支援流式、攔截器、負載均衡
  4. 安全警示: **嚴禁反序列化不可信數據**,Java 原生序列化有已知 RCE 漏洞鏈 (Commons Collections 等)

理解原生序列化通訊原理,有助於理解上層框架 (Retrofit/gRPC) 的底層行為,但**生產系統請優先選擇成熟的序列化協議與通訊框架**。

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