Cookie 在 Web 應用中廣泛用於維持客戶端與伺服器狀態,但 Java ME 平台並未內建支援。傳統替代方案 URL Rewriting 複雜且易出錯。本文完整呈現 Cookie 在 J2ME 上的實作原理與程式碼,涵蓋取得、解析、儲存、發送四大核心步驟,並提供可直接整合的 Cookie JavaBean 與管理邏輯。
Set-Cookie: name=value; Domain=...; Path=...; Expires=... 標頭Cookie: name=value 標頭關鍵匹配規則:Domain 尾端匹配 (如 .google.com 符合 mail.google.com);Path 為前綴匹配;Expires 過期自動清除;無 Expires 視為 Session 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 標頭,必須迭代處理。
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 為鍵,支援去重
}
RecordStore),應用重啟仍有效Hashtable<String, Cookie> (Key: name#path),應用結束自動失效,無須佔用 RMS 空間
// 從 RMS 與記憶體收集符合條件的 Cookie
String cookieHeader = collectCookie(requestUrl);
if (cookieHeader != null) {
conn.setRequestProperty("Cookie", cookieHeader);
}
collectCookie 邏輯:遍歷所有儲存 Cookie,檢查 Domain/Path/Expires,符合者以 name=value 格式以分號串接。
HttpConnectionManager 統一處理 Cookie、重導向、逾時、GZIP 等橫切關注點httpme 網路框架的完整實作Secure、HttpOnly 旗標支援,並處理跨網域 Cookie 隔離掌握這套機制,即可讓 J2ME 應用無縫對接依賴 Cookie 的既有 Web 服務,大幅降低整合複雜度。