欢迎大家关注本博,同时欢迎大家评论交流,可以给个赞哦!!!
谈到Cookie,就得说到会话跟踪技术,在Web发展早期,Cookie是会话跟踪技术的不二选择,拥有统一的实现标准。在基于无状态的HTTP协议进行服务搭建时,如何保持更加安全、简便的保持会话,就成了首要问题,Cookie技术就应运而生了。
Cookie是由一个键和一个值构成的,由服务器创建,随着服务器响应发送给客户端浏览器。客户端浏览器会把Cookie保存下来,下一次访问服务器时把服务器发送的Cookie再发送给服务器。单独来说Cookie的话,其实属于客户端应用,与之对应的Session属于服务器端应用,两者的交集就是保持会话的基础。
对于Cookie的内容不做过多的分析,在Cookie源码注释中都进行了标注。
Cookie
对于Servlet中Cookie,HttpServletRequest的getCookies提供了Cookie读取的功能,HttpServletResponse的addCookie提供了Cookie写入的功能。
package javax.servlet.http;
import java.text.MessageFormat;
import java.util.ResourceBundle;
/**
* 创建一个Cookie,Servlet发送到Web浏览器,由浏览器保存并稍后发送回服务器的少量信息.
* Cookie的值可以唯一地标识客户端,因此Cookie通常用于会话管理.
* Cookie有一个名称、一个值和可选属性(如注释、路径和域限定符、最长期限和版本号).
* 一些Web浏览器在处理可选属性的方式上存在缺陷,因此要谨慎使用它们来提高servlet的互操作性.
* Servlet使用HttpServletResponse.addCookie方法将Cookie发送到浏览器,该方法向HTTP响应头添加字段,以便一次发送一个cookie到浏览器.
* 浏览器预计支持每个Web服务器20个cookie,总共300个cookie,并且每个cookie大小限制为4kb.随着客户端浏览器的发展,这一项现在的容量已经大大提供了.
* 浏览器通过向HTTP请求头添加字段来将cookies返回给servlet.可以使用HttpServletRequest.getCookies方法从请求中检索Cookies.
* 多个cookie可能具有相同的名称,但路径属性不同.
* Cookie会影响使用它们的网页的缓存.HTTP1.0不缓存使用此类创建的Cookie的页面.此类不支持用HTTP1.1定义的缓存控件.
* 此类同时支持版本0(Netscape的Cookie规范)和版本1(W3C的RFC2109规范)Cookie规范.默认情况下,Cookie是使用版本0创建的,以确保最佳互操作性.
*/
public class Cookie implements Cloneable {
/**
* 错误信息模板位置.
*/
private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
/**
* 错误信息模板加载.
*/
private static ResourceBundle lStrings = ResourceBundle.getBundle(LSTRING_FILE);
/**
* Cookie名称.
*/
private String name; // NAME= ... "$Name" style is reserved
/**
* Cookie值.
*/
private String value; // value of NAME
/**
* Cookie用处说明.
*/
private String comment; // ;Comment=VALUE ... describes cookie's use
/**
* 可以访问该Cookie的域名.
*/
private String domain; // ;Domain=VALUE ... domain that sees cookie
/**
* 该Cookie的失效时间.
*/
private int maxAge = -1; // ;Max-Age=VALUE ... cookies auto-expire
/**
* 该Cookie的使用路径.
*/
private String path; // ;Path=VALUE ... URLs that see the cookie
/**
* 该Cookie是否仅被使用安全协议传输.安全协议有HTTPS、SSL等.
*/
private boolean secure; // ;Secure ... e.g. use SSL
/**
* 该Cookie使用的版本号.0表示遵循Netscape的Cookie规范、1表示遵循W3C的RFC2109规范.
*/
private int version = 0; // ;Version=1 ... means RFC 2109++ style
/**
* Constructs.初始参数包括name和value.
* name:必须遵循RFC 2109规范,只能包含ASCII字母数字字符,不能包含逗号、分号、空格或以$字符开头.创建后无法更改cookie的名称.
* value:可以是服务器选择发送的任何内容.
* 默认情况下,cookies是根据Netscape cookie规范创建的。可以使用setVersion方法更改版本.
* name不允许出现如下情况:
* 非Java保留标记,不区分大小写情况下,不等于Commet、Discard、Domain、Expires、Max-Age、Path、Secure、Version,不以$开头.
* @param name Cookie名.
* @param value Cookie值.
*/
public Cookie(String name, String value) {
if (!isToken(name) || name.equalsIgnoreCase("Comment") // rfc2019
|| name.equalsIgnoreCase("Discard") // 2019++
|| name.equalsIgnoreCase("Domain") || name.equalsIgnoreCase("Expires") // (old cookies)
|| name.equalsIgnoreCase("Max-Age") // rfc2019
|| 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;
}
/**
* 设置commet.
*/
public void setComment(String purpose) {
comment = purpose;
}
/**
* 获取commet.
*/
public String getComment() {
return comment;
}
/**
* 设置domain.
*/
public void setDomain(String pattern) {
domain = pattern.toLowerCase(); // IE allegedly needs this
}
/**
* 获取domain.
*/
public String getDomain() {
return domain;
}
/**
* 设置maxAge.
*/
public void setMaxAge(int expiry) {
maxAge = expiry;
}
/**
* 获取maxAge.
*/
public int getMaxAge() {
return maxAge;
}
/**
* 设置path.
*/
public void setPath(String uri) {
path = uri;
}
/**
* 获取path.
*/
public String getPath() {
return path;
}
/**
* 设置seure.
*/
public void setSecure(boolean flag) {
secure = flag;
}
/**
* 获取secure.
*/
public boolean getSecure() {
return secure;
}
/**
* 获取name.
*/
public String getName() {
return name;
}
/**
* 设置value.
*/
public void setValue(String newValue) {
value = newValue;
}
/**
* 获取value.
*/
public String getValue() {
return value;
}
/**
* 获取version.
*/
public int getVersion() {
return version;
}
/**
* 设置version.
*/
public void setVersion(int v) {
version = v;
}
private static final String tspecials = ",; ";
/**
* 测试字符串,如果该字符串在Java语言中算作保留标记,则返回true.
*/
private boolean isToken(String value) {
int len = value.length();
for (int i = 0; i < len; i++) {
char c = value.charAt(i);
if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1)
return false;
}
return true;
}
/**
* 重写clone.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e.getMessage());
}
}
}
若文中存在错误和不足,欢迎指正!
本博微信公众号“超哥说码”,欢迎大家订阅,公众号正在完善中,会及时将更优质的博文推送于您!