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

J2ME 平台 Cookie 技術完整實作:從原理到程式碼

     編輯:J2ME

引言:J2ME 缺失 Cookie 支援的解決之道

Cookie 在 Web 應用中廣泛用於維持客戶端與伺服器狀態,但 Java ME 平台並未內建支援。傳統替代方案 URL Rewriting 複雜且易出錯。本文完整呈現 Cookie 在 J2ME 上的實作原理與程式碼,涵蓋取得、解析、儲存、發送四大核心步驟,並提供可直接整合的 Cookie JavaBean 與管理邏輯。

Cookie 工作原理回顧

  1. 伺服器回應中包含 Set-Cookie: name=value; Domain=...; Path=...; Expires=... 標頭
  2. 客戶端解析並儲存 Cookie
  3. 後續請求自動檢查 Domain/Path/Expires,符合條件則附加 Cookie: name=value 標頭

關鍵匹配規則:Domain 尾端匹配 (如 .google.com 符合 mail.google.com);Path 為前綴匹配;Expires 過期自動清除;無 Expires 視為 Session Cookie。

三大核心實作步驟

步驟一:從回應取得 Cookie

利用 HttpConnection.getHeaderFieldKey(int index) 迭代所有標頭,擷取 Set-Cookie 與 SessionID (部分伺服器自定義):

String cookieVal = null;
String key = null;
int i = 0;
final String SET_COOKIE = "Set-Cookie";
final String SESSION_ID = "SessionID";

while ((key = conn.getHeaderFieldKey(i)) != null) {
    if (SET_COOKIE.equalsIgnoreCase(key) || SESSION_ID.equalsIgnoreCase(key)) {
        cookieVal = conn.getHeaderField(i);
        saveCookie(cookieVal, url);
    }
    i++;
}

注意:單次回應可能包含多個 Set-Cookie 標頭,必須迭代處理。

步驟二:解析與持久化儲存

Cookie JavaBean 設計

package com.j2medev.lomol.model;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;

public class Cookie {
    private String path = "";
    private String name = "";
    private String value = "";
    private long expire = SESSION_COOKIE;
    public static final long SESSION_COOKIE = 0;

    // Getter/Setter 略...

    // 序列化至 RMS
    public void serialize(DataOutputStream dos) throws IOException {
        dos.writeUTF(name);
        dos.writeUTF(value);
        dos.writeUTF(path);
        dos.writeLong(expire);
    }

    // 從 RMS 反序列化
    public static Cookie deserialize(DataInputStream dis) throws IOException {
        Cookie c = new Cookie();
        c.name = dis.readUTF();
        c.value = dis.readUTF();
        c.path = dis.readUTF();
        c.expire = dis.readLong();
        return c;
    }

    // 解析 Set-Cookie 字串
    public static Cookie parseCookie(String header, String requestUri) {
        Cookie c = new Cookie();
        StringUtil su = new StringUtil(header, ";"); // 自訂分割器
        while (su.hasMoreTokens()) {
            String token = su.nextToken().trim();
            int eq = token.indexOf('=');
            if (eq == -1) continue;
            String n = token.substring(0, eq);
            String v = token.substring(eq + 1);
            if ("path".equalsIgnoreCase(n)) c.setPath(v);
            else if ("expires".equalsIgnoreCase(n)) c.setExpire(StringUtil.parseDate(v));
            else if ("domain".equalsIgnoreCase(n)) { /* 暫不處理 */ }
            else { c.setName(n); c.setValue(v); }
        }
        if (c.getPath().isEmpty()) c.setPath(requestUri);
        return c;
    }

    public boolean isExpired() {
        return expire != SESSION_COOKIE && expire - System.currentTimeMillis() < 0;
    }

    // equals/hashCode 以 name+path 為鍵,支援去重
}

儲存策略

  • 持久 Cookie (有 Expires):序列化後寫入 RMS (RecordStore),應用重啟仍有效
  • Session Cookie (無 Expires):僅保存在記憶體 Hashtable<String, Cookie> (Key: name#path),應用結束自動失效,無須佔用 RMS 空間

步驟三:請求前組裝並發送 Cookie


// 從 RMS 與記憶體收集符合條件的 Cookie
String cookieHeader = collectCookie(requestUrl);
if (cookieHeader != null) {
    conn.setRequestProperty("Cookie", cookieHeader);
}

collectCookie 邏輯:遍歷所有儲存 Cookie,檢查 Domain/Path/Expires,符合者以 name=value 格式以分號串接。

整合建議與擴展

  • 封裝為 HttpConnectionManager 統一處理 Cookie、重導向、逾時、GZIP 等橫切關注點
  • 參考《Java ME 核心技術與最佳實踐》書中 httpme 網路框架的完整實作
  • 生產環境建議加入 Secure、HttpOnly 旗標支援,並處理跨網域 Cookie 隔離

掌握這套機制,即可讓 J2ME 應用無縫對接依賴 Cookie 的既有 Web 服務,大幅降低整合複雜度。

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