Java ME (MIDP) 原生不支援 Cookie,導致無法像瀏覽器那樣自動維持會話狀態,開發者常被迫使用 URL 重寫。本文詳述在 MIDP 上手工實現完整 Cookie 機制的三大步驟:獲取、存儲、發送。
Set-Cookie: name=value; Path=/; Domain=.example.com; Expires=...。Cookie: name=value(符合 Domain/Path/未過期)。private static final String SET_COOKIE = "Set-Cookie";
private static final String COOKIE = "Cookie";
public void extractCookies(HttpConnection conn, String url) {
int i = 0;
String key;
while ((key = conn.getHeaderFieldKey(i)) != null) {
if (SET_COOKIE.equalsIgnoreCase(key)) {
String cookieVal = conn.getHeaderField(i);
saveCookie(cookieVal, url);
}
i++;
}
}
需遍歷所有同名頭欄位(一個回應可下發多個 Cookie)。
public class Cookie implements Serializable {
private String name, value, path, domain;
private long expires; // 0 = session cookie
// getter/setter、equals/hashCode(按 name+path+domain)、isExpired()
// 序列化:DataOutputStream writeUTF/writeLong
// 反序列化:DataInputStream readUTF/readLong
// 靜態解析方法 parseCookie(String header, String requestUri)
}
Hashtable 內存,MIDlet 退出自動失效。
public void attachCookies(HttpConnection conn, String url) {
String cookieHeader = collectMatchingCookies(url);
if (cookieHeader != null) {
conn.setRequestProperty(COOKIE, cookieHeader);
}
}
private String collectMatchingCookies(String url) {
// 1. 從 RMS 讀取所有持久 Cookie
// 2. 合併內存會話 Cookie
// 3. 過濾:domainMatch(url) && pathMatch(url) && !isExpired()
// 4. 拼接 "name1=value1; name2=value2"
}
.example.com 匹配 api.example.com、example.com;不匹配 other.com。/app 匹配 /app/servlet、/app/index.html;不匹配 /other。將上述邏輯封裝為 HttpConnectionWrapper 或攔截器,業務代碼無感知:
HttpConnection conn = (HttpConnection) Connector.open(url);
CookieManager.attachCookies(conn, url);
// 發送請求、讀取回應
CookieManager.extractCookies(conn, url);
《Java ME 核心技術與最佳實踐》書中 httpme 框架包含生產級 Cookie 實現,可直接引用。
在 Java ME 上實現 Cookie 需:解析 Set-Cookie 頭 → 領域模型 + RMS/內存雙層存儲 → 請求前按域路徑過濾拼裝 Cookie 頭。封裝良好後,網絡層即可透明支援會話保持,大幅簡化業務開發。