初探Tomcat源码 (6) —— Cookie

        HTTP协议本身是无状态的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机的关系一样。
但是很多时候,我们需求区分用户发来的请求是否来自于同一个浏览器,例如用户只用登陆一次,就可以了,后来的请求都带着这个登陆信息,就不用重复登陆了。
所以客户端和服务器端的交互,需要携带一部分的状态信息,CookieSession的解决方案应运而生。
 
就好比我们到超市买东西,cookie就像我们的会员卡,存放在客户那,每次消费完都记录一下,下次买的时候就知道有多少积分了。而session就像是购物车,存放在服务端,我们每次进超市都会生成一个购物车实例,我们和服务器的交互就相当于来到不同的货架买东西,session都给我们记录着,一直到我们走出超市的时候才回收,否则我们就不记得自己买过什么了。
综上所述,cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
Cookie对应会员卡,是存储在客户端的一个小文本文件。客户每次访问服务器都要附带着的。
而Session通常存放在服务器的内存中,用来存储客户的临时状态信息,超时回收。一般是,客户第一次访问,服务器就会创建一个Session并把ID返回给客户,客户每次访问的时候都需要携带着这个ID号,用来唯一标识这个客户,直到离开或者超时。  
所以客户需要有携带这个SessionID的载体,可以直接放到Cookie中;也可以通过URL重写,放到URL中;还可以通过表单隐藏字段,来跟随表单传过来。
后两者可以防止人为禁用cookie。

 


Cookies


        Cookies会随着每次请求被发送到服务器,所以其大小会影响网络传输效率,应尽量减少,而且浏览器也对Cookie的大小有所限制。大多数浏览器支持最大为4096字节。


另外,Cookies的内容是
明文保存
的,所以不应该保存隐私的信息。


        Cookies实际上是一条附在请求头部,key为Cookie的键值链【key1=val1;key2=val2;……】,每个键值又被成为一个Cookie。


由于Cookies依附在请求中传输,所以同样被Request解析,存放在Request中。


 


        Cookie并非只能在服务端读写,在客户端的浏览器中也可以实现对它的读写访问。


<
script
type
=
"text/javascript"
>

var cookie = "name=jscai;id=3472" ;
document.cookie = cookie;

</
script
>


 


        在Tomcat5.0中,Cookies的标准实现为:org.apache.tomcat.util.http.Cookies,这个类负责解析管理cookie。Request要解析cookie,先MimeHeaders


        Cookies相当于Cookie的数组,一个客户信息的键值链。


ServerCookie
scookies
[]=
new
ServerCookie[
INITIAL_SIZE
];


 


Cookies的可循环通过recycle()来实现。


public
void
recycle() {

for ( int i=0; i< cookieCount ; i++ ) {

if ( scookies [i]!= null )

scookies [i].recycle();

}
cookieCount =0;
unprocessed = true ;

}

 


ServerCookie


        Java中标准的Cookie实现为javax.servlet.http.Cookie,而Coyote中再封装改良一下:org.apache.tomcat.util.http.ServerCookie。


主要为了添加两个功能:


1、对象的
可循环
,节省空间和GC的开支;


2、使用
MessageBytes存储字符属性
,在字节流字符串频繁交互的网络环境,使用MessageBytes来代替String能有效提高性能,而且也可循环。


 


Cookie是一个key-value的键值对,记录了客户的信息。

private MessageBytes name = MessageBytes. newInstance ();
private MessageBytes value = MessageBytes. newInstance ();

 


Cookie通过recycle来实现对象的循环。


public
void
recycle() {


     
path
.recycle();


     
name
.recycle();


     
value
.recycle();


     
comment
.recycle();


     
maxAge
=-1;


     
path
.recycle();


     
domain
.recycle();


     
version
=0;


     
secure
=
false;

}

— — 参考Tomcat 5.0源代码