理解Cookie
当一个用户通过HTTP访问一个服务器时,服务器会将一些Key/Value键值对返回给客户端浏览器,并给这些数据加上一些限制条件;在条件符合时,这个用户再次访问这个服务器时,数据又被完整地带回给服务器;
好比,你去超市购物,第一次给你办了张购物卡,在这张购物卡上存放了你的个人信息,下次再来购物的时候,超市会识别你的购物卡,直接购物即可;
当初设计Cookie时,实际上考虑的是为了记录用户在一段时间内访问Web应用的行为路径;由于HTTP是一种无状态的协议,当用户的一次访问请求结束后,服务器就无法知道下次来访问的还是不是上次访问的用户;
例如,在一个很短的时间内,如果与用户相关的数据被频繁访问,可以针对这个数据做缓存,这样可以大大提高数据的访问性能; Cookie的作用正是如此,由于是同一个客户端发出的请求,每次发出的请求都会带有第一次访问时服务端设置的信息,这样服务端就可以根据Cookie的值来划分访问的用户;
Cookie的属性项
Cookie有两个版本:Version 0和Version 1;它们有两种设置响应头的标识,分别是"Set-Cookie"和"Set-Cookie2";
Servlet规范并不支持Set-Cookie2响应头,在实际应用中Set-Cookie2的一些属性项却可以设置在Set-Cookie中;
Cookie是如何工作的
String getCookie(Cookie[] cookies,String key){
if(cookie != null){
for(Cookie cookie : cookies){
if(cookie.getName().equals(key)){
return cookie.getValue();
}
}
}
return null;
}
@Override
public void doGet(HttpServeltRequest request,
HttpServletResponse response) throws IOException,ServletException {
Cookie[] cookies = request.getCookies();
String userName = getCookie(cookies,"username");
String userAge = getCookie(cookies,"userAge");
if(userName == null){
response.addCookie(new Cookie("username","junshan"));
}
if(userAge == null){
response.addCookie(new Cookie("userAge","28"));
}
response.getHeaders("Set-Cookie");
}
当我们用Servlet 3.0规范创建一个Cookie对象时,该Cookie即支持Version 0也支持Version 1;如果你设置了Version 1中的配置项,即使你没有设置版本号,Tomcat在最后构建HTTP响应头时也会自动将Version的版本设置为1;
下图是Tomcat创建Set-Cookie响应头的时序图;
从上图可以看出,真正构建Cookie是在Response类中,调用generateCookieString()将Cookie对象构造成一个字符串,构造的字符串的格式如userName="junshan";Version="1";Domain="xulingbo.net";Max-Age=1000。最后将这个字符串命名为Set-Cookie添加到MimeHeaders中;
当我们通过response.addCookie创建多个Cookie时,即每次调用addCookie时都会创建一个Header;但是,最终在请求返回时构造的HTTP响应头是否将相同Header标识的Set-Cookie值进行合并;在构建HTTP返回字节流的时候,是将Header中所有的项顺序地写出,而没有进行任何的修改;所以,浏览器在接收HTTP返回的数据的时候是分别解析每一个Header项的;
当我们请求某个URL路径时,浏览器会根据这个URL路径将符合条件的Cookie放入Request请求头中传回给服务端,服务端根据request.getCookies()来取得所有的Cookie;
使用Cookie的限制
Cookie是HTTP头中的一个字段,不同浏览器对Cookie的大小和数量都有限制;
理解Session
Cookie可以让服务端程序跟踪每个客户端的访问,但是每次客户端的访问都必须传回这些Cookie;如果Cookie很多,就无形地增加了客户端和服务端的数据传输量,而Session就是为了解决这个问题;
同一个客户端每次和服务端交互时,不需要每次都传回所有的Cookie值,而是只要传回一个ID,这个ID是客户端第一次访问服务器时生成的,每个客户端是唯一的;
Session与Cookie
Session是如何基于Cookie来工作的;实际上有以下三种方式可以让Session正常工作;
1.基于URL Path Parameter,默认支持;
2.基于Cookie,如果没有修改Context容器的Cookies标识,则默认也是支持的;
3.基于SSL,默认不支持,只有connector.getAttribute("SSLEnabled")为true时才支持;
Session是如何工作的
有了SessionID,服务端就可以创建HttpSession对象了,第一次触发通过request.getSession()方法;如果当前SessionID还没有对应的HttpSession对象,那就创建一个新的,并将这个对象加到org.apache.catalina.Manager的sessions容器中保存;
Manager类将管理所有的Session的生命周期,Session过期将被回收,服务器关闭,Session将被序列化到磁盘等;只要这个HttpSession对象存在,用户就可以根据Session ID来获取这个对象,也就做到了对状态的保持;