1.cookie是首先由服务器向浏览器发送的
cookie最早来源于服务器,它像浏览器发送的响应头,如下:
HTTP/1.1 200
Server:...
Set-Cookie: name=admin
Set-Cookie: nickname=nick_admin;
Set-Cookie: email="[email protected]";
Set-Cookie: phone=1111111
……
Server:...
Set-Cookie: name=admin
Set-Cookie: nickname=nick_admin;
Set-Cookie: email="[email protected]";
Set-Cookie: phone=1111111
……
每一个Cookie信息都用一个Set-Cookie头传送。实现如上效果的servlet代码如下:
Cookie ckName = new Cookie("name", name); Cookie ckNickname = new Cookie("nickname", nickname); ckNickname.setMaxAge(365 * 24 * 3600); Cookie ckEmail = new Cookie("email", "[email protected]"); Cookie ckPhone = new Cookie("phone", "1111111"); //奇怪,针对chrome就不生成JSESSIONID response.addCookie(ckName); response.addCookie(ckNickname); response.addCookie(ckEmail); response.addCookie(ckPhone);
2.浏览器返回cookie信息
浏览器在收到服务器发送的cookie时,存储起来,并在每次向服务器请求时重新将cookie信息返回。如下:
POSE /** HTTP/1.1
accept : image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
accept-language : zh-cn
user-agent : Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727)
accept-encoding : gzip, deflate
host : localhost:8080
connection : Keep-Alive
Cookie: name=admin; nickname=nick_admin; email="[email protected]"; phone=1111111; JSESSIONID=CDF550D953DAB0E59A57D7D1CCFDDD30
accept : image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
accept-language : zh-cn
user-agent : Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727)
accept-encoding : gzip, deflate
host : localhost:8080
connection : Keep-Alive
Cookie: name=admin; nickname=nick_admin; email="[email protected]"; phone=1111111; JSESSIONID=CDF550D953DAB0E59A57D7D1CCFDDD30
3. http请求、发送小结
通过这样一来一回,返回的cookie信息是一致的(你可以改),就可以判断唯一用户了。这种方式也可以用来实现session。
读取http请求中的cookie方法如下:
String lastNickname = null; Cookie[] cks = request.getCookies(); for (int i = 0; cks != null && i < cks.length; i++) { if ("nickname".equals(cks[i].getName())) { lastNickname = cks[i].getValue(); break; } }
或者也可以这么取
String cookieHeader = request.getHeader("Cookie");
可以通过:http://localhost:8080/Test_servlet/ch7/CookieServlet1?name=admin&nickname=nick_admin
查看效果。
3.Cookie源代码
Cookie类,真是难得一见的类,不是接口。
package javax.servlet.http; import java.text.MessageFormat; import java.util.ResourceBundle; public class Cookie implements Cloneable { private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings"); private String name; private String value; private String comment; private String domain; private int maxAge = -1; private String path; private boolean secure; private int version = 0; private static final String tspecials = ",; "; public Cookie(String name, String value) { if ((!(isToken(name))) || (name.equalsIgnoreCase("Comment")) || (name.equalsIgnoreCase("Discard")) || (name.equalsIgnoreCase("Domain")) || (name.equalsIgnoreCase("Expires")) || (name.equalsIgnoreCase("Max-Age")) || (name.equalsIgnoreCase("Path")) || (name.equalsIgnoreCase("Secure")) || (name.equalsIgnoreCase("Version")) || (name.startsWith("$"))) { String errMsg = lStrings.getString("err.cookie_name_is_token"); Object[] errArgs = new Object[1]; errArgs[0] = name; errMsg = MessageFormat.format(errMsg, errArgs); throw new IllegalArgumentException(errMsg); } this.name = name; this.value = value; } public void setComment(String purpose) { this.comment = purpose; } public String getComment() { return this.comment; } public void setDomain(String pattern) { this.domain = pattern.toLowerCase(); } public String getDomain() { return this.domain; } public void setMaxAge(int expiry) { this.maxAge = expiry; } public int getMaxAge() { return this.maxAge; } public void setPath(String uri) { this.path = uri; } public String getPath() { return this.path; } public void setSecure(boolean flag) { this.secure = flag; } public boolean getSecure() { return this.secure; } public String getName() { return this.name; } public void setValue(String newValue) { this.value = newValue; } public String getValue() { return this.value; } public int getVersion() { return this.version; } public void setVersion(int v) { this.version = v; } private boolean isToken(String value) { int len = value.length(); for (int i = 0; i < len; ++i) { char c = value.charAt(i); if ((c < ' ') || (c >= '') || (",; ".indexOf(c) != -1)) return false; } return true; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e.getMessage()); } } }
参考:《深入体验Java_Web开发内幕-核心基础\》
……
……