先来谈谈我对session和cookie的理解,事实上,只要你去面试web开发,面试官十有八九会问这个问题。

cookie和session经常被放在一起问,其实在我看来这两个东西完全是两个不一样的。

1.cookie是存在于浏览器,随意打开一个网址,用火狐的调试工具,随意选取一个链接,查看其请求头。你就会看到cookie的信息。如下图所示。

如上图所示,我们访问了新浪网,通过火狐浏览器的调试窗口可以看到cookie存在于请求头也就是httprequest中,并且是以键值对(数组)的形式存在。事实上,在java的servlet体系里,我们可以通过如下方式获取cookie.

HttpServletRequest req=ServletActionContext.getRequest();
        Cookie[] cookies=req.getCookies();
        for(int i=0;i<cookies.length;i++){
            Cookie cookie=cookies[i];
            System.out.println("name:"+cookie.getName()+",domain"+cookie.getDomain()+",value:"+cookie.getValue()+",maxage:"+cookie.getMaxAge());
        }

我们在一个action中加入如下代码,并且访问这个action,则可以看到控制台打印出如下信息。

cookie对象有几个属性,如name,domain,value,maxage等,具体的意义可以参考servlet的api文档。

以上的请求的cookie是我首次访问某一个网站的链接时候产生的。可以看到cookie数组中只有一个元素。这边先注意一下,后续会有更进一步的说明。

说了获取cookie数组和cookie,我们一定也想知道如何把我们自己的一些信息放进cookie,其实很简单。http的一次请求总是伴随着一次响应,我们就将cookie信息放入到响应中,传递给浏览器。在java下代码是这样写的。

HttpServletResponse res=ServletActionContext.getResponse();
        Cookie cookie=new Cookie("xdx", "i'm xdx");
        res.addCookie(cookie);

可以看到当我们发起这个请求时,在响应头有下列信息。

也就是通过这次请求,我们把xdx=i'm xdx 这个cookie通过response放进了浏览器。

当我们在访问该网站上的其他页面的时候,在请求头都将带有这个cookie。如下图所示。

而假如我们清楚历史记录,包括cookie。

再次访问该网站的某一个地址。刚才我们加进去的cookie就不存在了。

理解这一点对我们后面解读cookie与session的关系很重要。

2.那session又是一个什么样的东西呢?在我的理解,session是一种持久的会话,它的存在主要是为了克服http无状态的特点,关于http无状态,或者说没有记忆,这里不多阐述,涉及到计算机网络的知识,简单来说就是http一次请求对应一次响应,在这个过程中会携带一些信息,但这些信息也仅仅在这个过程中有效。当一个请求结束,我们进入下一个请求的时候,上一个请求里面的信息对当前的请求就没什么意义了,因为当前的请求根本不会知道上一个请求里面所包含的信息。

那么当我们需要一些在各个请求都能公用的信息的时候,该怎么办呢?有很多办法,可以把信息存在数据库,然后每次从数据库去取出来,当然io存取会浪费很多时间,它仅仅针对大数据量。还有一种就是将这些信息存在内存当中。没错session其实就是这样一种对象,他把项目当中一些常用的信息存在内存当中,这些常用的信息通常是跟用户相关的,比如用户名,用户昵称,用户角色等。因为他们需要经常用到,所以把这些信息存在session中进行管理再好不过了。

在面试的时候,如果你不会回答,回答一个cookie是存在浏览器里,session是存储在服务器里面的准没错。

那我们来看看我们如何获取一个session呢。

在servlet体系里,我们可以用如下代码来获取session。

HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession httpSession=request.getSession();
        System.out.println(httpSession);

我们来查阅HttpServletRequest的源码,看看其getSession()方法。

 /**
     *
     * Returns the current session associated with this request,
     * or if the request does not have a session, creates one.
     *
     * @return        the <code>HttpSession</code> associated
     *            with this request
     *
     * @see    #getSession(boolean)
     *
     */

    public HttpSession getSession();

它的解释是返回当前与request关联的session,如果这个请求不存在session,就新建一个。

我们在两个请求中加入上述代码并运行,得到如下结果。

可以看到在整个项目内,这个session被共享着调用。

3.那么session和cookie到底有什么关系呢?

简单点说,每一个session对象都有一个sessionId,而在cookie数组中,又一个元素叫做JSESSIONID,服务器将session对象的sessionId,以名称叫做JSESSIONID,值为sessionId的形式存入cookie数组中,这样cookie和session就发生了关联。

上述的过程可以用类似如下的代码来实现。

HttpServletRequest req=ServletActionContext.getRequest();
        HttpServletResponse res=ServletActionContext.getResponse();
        Cookie cookie=new Cookie("JSESSIONID", req.getSession().getId());

当然我们并不需要写这个代码,servlet自动帮我们完成了如上的操作。

4.当我们首次某个请求的时候,servlet通过request.getSession得到当前的HttpSession,并且得到其sessionId,并且检查此时的cookie数组中是否有JSESSIONID这个cookie,如果没有的话,就将当前的sessionId作为值加入cookie数组。

我们将浏览器缓存清除,这样cookie中就没有JSESSIONID了,然后我们访问一个action。如下。

可以看到在这个请求的请求头中,cookie数组里面是不包含JSESSIONID这个cookie的,所以在响应头中servlet把它set进去了。

我们再次访问这个网站的任意action。如下图。

可以看到cookie中已经包含了JSESSIONID,并且它的值跟上一个请求set进去的是一样。

5.当我们清空浏览器的时候,session会消失吗?

这个问题经常被面试官作为进阶的问题来问应聘者,它包含着一些陷阱。因为很多时候当我们清空浏览器以后,确实需要重新登录系统才可以操作,所以很多人自然而然认为清空浏览器缓存(包含cookie)以后。session就会消失。

其实这种结论是错误的。要知道,session是存在于服务器的,你清除浏览器缓存,只是清除了cookie,跟session一点关系都没有。那么为什么我们却不能访问网站,而需要重新登录了呢?

这就是要回到我们前面说的session是如何产生的,当我们使用request.getSession()方法的时候,该方法的注释说,当session不存在的时候,servlet容器会新建一个session,那么servlet容器是如何判断session到底存不存在呢?

还记得我们发起请求的时候,请求头中cookie信息吧,没错,servlet从请求头中取出cookie,查看cookie数组中是否存在JSESSIONID这个cookie,如果没有的话,新建一个,如果有的话,在拿这个cookie的值作为sessionId去内存中寻找session,找得到的话就拿出来用,找不到就新建。

以上的逻辑可以用如下代码的模拟。

    HttpServletRequest req=ServletActionContext.getRequest();
        Cookie JSESSIONID=null;
        Cookie[] cookies=req.getCookies();
        for(int i=0;i<cookies.length;i++){
            Cookie cookie=cookies[i];
            if(cookie.getName().equals("JSESSIONID")){
                JSESSIONID=cookie;
            }
        }
        if(JSESSIONID==null){
            createSession();//创建一个session
        }else{
            HttpSession session=findSessionBySessionId(JSESSIONID.getValue());//通过sessionId获取session
            if(session==null){
                createSession();//创建一个session
            }else{
                return session;
            }
        }

6.讨论几种极端情况。

第一种:当项目正常运行,我们清空浏览器,cookie和session会发生什么变化。

因为清空了浏览器,所以不会存在JSESSIONID这个cookie,servlet无法找到对应的session,所以他会新建一个session,然后在本次请求的响应中将session传入cookie中。

下一次请求,cookie数组中就带有JSESSIONID这个cookie了,servlet就可以找到对应的session,沿用即可。

第二种:浏览器正常,项目重启,cookie和session会发生什么变化。

因为项目重启,内存中的一切session都消失了,虽然访问一个action,请求头中有JSESSIONID这个cookie,但是通过它的值(sessionId)并不能找到session(因为根本没有),所以还是得重新创建一个session,并且这个session的sessionId跟当前cookie数组中的JSESSIONID的值不一样,所以还是得通过response去更新JSESSIONID,将之前的换成新的。

有兴趣的同学可以去试验一下。

cookie和session(一)的更多相关文章

  1. Cookie和Session的总结

    1.开篇 在之前学习这一段的时候我一直有点没弄清楚,其实对Session这块的理解还可以,但是Cookie感觉始终还是欠缺点火候.之后的很长一段时间都基本上很少用Cookie了,渐渐的也淡忘了这一块的 ...

  2. java的会话管理:Cookie和Session

    java的会话管理:Cookie和Session 1.什么是会话 此处的是指客户端(浏览器)和服务端之间的数据传输.例如用户登录,购物车等 会话管理就是管理浏览器客户端和服务端之间会话过程产生的会话数 ...

  3. Cookie和Session的那些事儿

    Cookie和Session都是为了保持用户的访问状态,一方面为了方便业务实现,另一方面为了简化服务端的程序设计,提高访问性能.Cookie是客户端(也就是浏览器端)的技术,设置了Cookie之后,每 ...

  4. django的cookie和session以及内置信号、缓存

    cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...

  5. Cookie和Session的区别

    前言 HTTP是一种无状态的协议,为了分辨链接是谁发起的,就需要我们自己去解决这个问题.不然有些情况下即使是同一个网站我们每打开一个页面也都要登录一下.而Session和Cookie就是为解决这个问题 ...

  6. 本地数据Store。Cookie,Session,Cache的理解。Timer类主要用于定时性、周期性任务 的触发。刷新Store,Panel

    本地数据Store var monthStore = Ext.create('Ext.data.Store', { storeId : 'monthStore', autoLoad : false, ...

  7. Cookie与Session

    再说Cookie与Session之前,先要了解一下http协议. 何为http协议: http协议即超文本传输协议,一种基于浏览器请求与服务器响应的协议,该协议主要的特点就是它是一种无状态的协议(只针 ...

  8. 【转】Cookie和Session区别和联系详解

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  9. 理解Cookie和Session机制(转)

    目录[-] Cookie机制 什么是Cookie 记录用户访问次数 Cookie的不可跨域名性 Unicode编码:保存中文 BASE64编码:保存二进制图片 设置Cookie的所有属性 Cookie ...

  10. cookie 和session 的区别详解

    这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择, 都纪 ...

随机推荐

  1. Spring的69个知识点

    目录 Spring 概述 依赖注入 Spring beans Spring注解 Spring数据访问 Spring面向切面编程(AOP) Spring MVC Spring 概述 1. 什么是spri ...

  2. FPGA DDR3调试

    FPGA DDR3调试 Spartan6 FPGA芯片中集成了MCB硬核,它可以支持到DDR3.在Xilinx的开发工具Xilinx ISE中提供了MIG IP核,设计者可以用它来直接生成 DDR3 ...

  3. Git版本控制管理教程(一):介绍

    我的个人博客地址:damienzhong.com 原文链接:点击打开链接 1.1 背景 数据是短暂的,且容易丢失的,特别是作为开发人员的我们每天频繁的对项目代码进行更新,容易产生错误代码的变更或者项目 ...

  4. 异常:This application has no explicit mapping for /error, so you are seeing this as a fallback.

    出现这个异常说明了跳转页面的url无对应的值. 原因1: Application启动类的位置不对.要将Application类放在最外侧,即包含所有子包 原因:spring-boot会自动加载启动类所 ...

  5. Git详解及 github与gitlab使用

    1.1 关于版本控制 1.1.1 本地版本控制 本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别.这么做唯一的 好处就是简单,但是特别容易犯错.有 ...

  6. hdu 3829 Cat VS Dog 二分匹配 最大独立点集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3829 题目大意: 给定N个猫,M个狗,P个小朋友,每个小朋友都有喜欢或者不喜欢的某猫或者某狗 管理员从 ...

  7. zzuli 1816: 矩形 排序思维

    1816: 矩形 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 179  Solved: 54 SubmitStatusWeb Board Descr ...

  8. PHP面向对象-----魔术方法

    PHP面向对象-----魔术方法 __get($name)--触发时机:当调用一个不访问的成员属性的时候,会自动触发,可以利用这个方法来完成对不可调用的属性进行调用,但是不能设置值 ___set($n ...

  9. 获取串口映射的COM端口号

    背景:近期由于项目需要,需要操作短信猫,当短信猫插入电脑后,会根据当前PC状况,映射COM口,这里需动态获取短信猫映射的COM端口号. 编程语言C#: 具体代码如下 public enum Hardw ...

  10. Java解决Hanoi问题

    package fa.ct; import java.util.Scanner; public class Hanoi { public static void hanoi(int num,char ...