先来谈谈我对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. SSM框架搭建(Spring+SpringMVC+MyBatis)与easyui集成并实现增删改查实现

    一.用myEclipse初始化Web项目 新建一个web project: 二.创建包 controller        //控制类 service //服务接口 service.impl //服务 ...

  2. Struts2-Tiles整合

    Apache Tiles是一个JavaEE应用的页面布局框架.Tiles框架提供了一种模板机制,可以为某一类页面定义一个通用的模板,该模板定义了页面的整体布局.布局由可以复用的多个块组成,每个页面可以 ...

  3. C#2.0中使用yield关键字简化枚举器的实现

    我们知道要使用foreach语句从客户端代码中调用迭代器,必需实现IEnumerable接口来公开枚举器,IEnumerable是用来公开枚举器的,它并不实现枚举器,要实现枚举器必需实现IEnumer ...

  4. javascript获取链接参数

    var url = "http://test.cn/index.php?class=9&id=2&key=88"; function parseQueryStrin ...

  5. Django 入门案例开发(下)——创建项目应用及模型类

    前面两章是在已经开发好的项目上用来描述环境和业务,这一章创建一个全新的项目来用作开发,你可以跟着我的步骤进行开发,如果有不理解的地方可以给我留言. 今天的任务是创建好项目和用户(users)应用及让它 ...

  6. PyCharm教程

    1.PyCharm3.0默认快捷键 2.PyCharm默认模板设置 3.字体设置 1.PyCharm3.0默认快捷键(翻译的)PyCharm Default Keymap 1.编辑(Editing) ...

  7. Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: Access denied

    装了fedora23后定时关机:sudo shutdown -h +60 弹出如下信息后立刻就关机了: Failed to call ScheduleShutdown in logind, proce ...

  8. let和const命令

    let命令 1.let用来声明变量,类似于var,但只在代码块内有效. { let a = 1; var b = 2; } console.log(a); //a is not defined con ...

  9. 智能合约开发环境搭建及Hello World合约

    如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇. 就先学习任何编程语言一样,入门的第一个程序都是Hello World.今天我们来一步一步从搭建以太坊智能合约 ...

  10. Python网络编程篇之select和epoll

    1. select 原理 在多路复⽤的模型中, ⽐较常⽤的有select模型和epoll模型. 这两个都是系统接⼝, 由操作系统提供. 当然, Python的select模块进⾏了更⾼级的封装. ⽹络 ...