cookie和session(一)
先来谈谈我对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(一)的更多相关文章
- Cookie和Session的总结
1.开篇 在之前学习这一段的时候我一直有点没弄清楚,其实对Session这块的理解还可以,但是Cookie感觉始终还是欠缺点火候.之后的很长一段时间都基本上很少用Cookie了,渐渐的也淡忘了这一块的 ...
- java的会话管理:Cookie和Session
java的会话管理:Cookie和Session 1.什么是会话 此处的是指客户端(浏览器)和服务端之间的数据传输.例如用户登录,购物车等 会话管理就是管理浏览器客户端和服务端之间会话过程产生的会话数 ...
- Cookie和Session的那些事儿
Cookie和Session都是为了保持用户的访问状态,一方面为了方便业务实现,另一方面为了简化服务端的程序设计,提高访问性能.Cookie是客户端(也就是浏览器端)的技术,设置了Cookie之后,每 ...
- django的cookie和session以及内置信号、缓存
cookie和session cookie和session的作用: cookie和session都记录了客户端的某种状态,用来跟踪用户访问网站的整个回话.两者最大的区别是cookie的信息是存放在浏览 ...
- Cookie和Session的区别
前言 HTTP是一种无状态的协议,为了分辨链接是谁发起的,就需要我们自己去解决这个问题.不然有些情况下即使是同一个网站我们每打开一个页面也都要登录一下.而Session和Cookie就是为解决这个问题 ...
- 本地数据Store。Cookie,Session,Cache的理解。Timer类主要用于定时性、周期性任务 的触发。刷新Store,Panel
本地数据Store var monthStore = Ext.create('Ext.data.Store', { storeId : 'monthStore', autoLoad : false, ...
- Cookie与Session
再说Cookie与Session之前,先要了解一下http协议. 何为http协议: http协议即超文本传输协议,一种基于浏览器请求与服务器响应的协议,该协议主要的特点就是它是一种无状态的协议(只针 ...
- 【转】Cookie和Session区别和联系详解
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...
- 理解Cookie和Session机制(转)
目录[-] Cookie机制 什么是Cookie 记录用户访问次数 Cookie的不可跨域名性 Unicode编码:保存中文 BASE64编码:保存二进制图片 设置Cookie的所有属性 Cookie ...
- cookie 和session 的区别详解
这些都是基础知识,不过有必要做深入了解.先简单介绍一下. 二者的定义: 当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择, 都纪 ...
随机推荐
- 使用javax.script包实现Java设置JS脚本中的变量
下面例子中,我们通过javax.script包ScriptEngine.put()方法设置JS脚本中的变量,JS把所有在线用户输出. package ajava.code.javase; import ...
- [认证授权] 5.OIDC(OpenId Connect)身份认证授权(扩展部分)
在上一篇[认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)中解释了OIDC的核心部分的功能,即OIDC如何提供id token来用于认证.由于OIDC是一个协议族,如果 ...
- c#鼠标点击TextBox控件后清空默认字体
方案(一) 脚本: <script type="text/javascript" language="javascript"> //得 ...
- R语言高性能编程(二)
接着上一篇 一.减少内存使用的简单方法1.重用对象而不多占用内存 y <- x 是指新变量y指向包含X的那个内存块,只有当y被修改时才会复制到新的内存块,一般来说只要向量没有被其他对象引用,就可 ...
- 学会WCF之试错法——安全配置报错分析
安全配置报错分析 服务端配置 <system.serviceModel> <bindings> <wsHttpBinding> <binding name = ...
- linux 安装nginx 详解
1 nginx安装环境 nginx是C语言开发,建议在linux上运行,本教程使用Centos6.5作为安装环境. n gcc 安装nginx需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没 ...
- html基本标签与属性
HTML 超文本标记语言 html5 建立一个HTML文件:文件名 . 后缀(html) 解析:就是去识别 注释:就是给开发人员开的批注------浏览器不去解析(不去输出) HTML的整体框 ...
- VeloView源码编译错误记录——VS manifest
编译环境 Win7 Visual Studio 2008 Win32 VeloView依赖关系 1)底层 Python Qt pcap boost eigen 2)中层 liblas: boost P ...
- Ansible(一) 配置安装
puppet ruby开发 salt python开发,有客户端,使用Rabbitmq消息队列,支持并发,在机器数量很多时效果比ansible好. ansible python开发, 没有客户端,基于 ...
- FreeRTOS 移植到WIN10
背景 标题表述的不准确,大意是移植到WIN10的PC机,Intel I5. 最近因为项目接触了FreeRTOS 实时操作系统,想对这个操作系统有一个更深入的了解,所以决定下载源码看看,下面这个链接的随 ...