web基础---->session的使用
前几天在博问中,看到有人提到了有关session的问题,决定自己整理写一下有关session的原理!说起session,cookie必须是要谈的!
目录
Cookie的介绍(参照计算机网络)
一、无形之中我们使用的cookie:
使用浏览器浏览网页时,当你要登陆时,网页上有一个记住密码或自动登陆的选项,当你选择时,你就使用了Cookie。那么在下次访问该网站时,你可能就已经自动地登陆了,而不需要从重输入用户名和密码
- 在HTTP响应报文中有一个cookie首部行;
- 在HTTP请求报文中有一个cookie首部行;
- 在用户端系统中保留有一个cookie文件,由用户浏览器管理;
- 在Web站点有一个后端数据库;
Cookie的使用
java中的response响应中加入cookie:
Cookie cookie = new Cookie("JSESSIONID", "123456");
cookie.setPath("/test");
response.addCookie(cookie);
java中的request请求中得到cookie:
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
String cookieName = cookie.getName();
String cookieValue = cookie.getValue();
System.out.println(cookieName + ", " + cookieValue);
}
Session的介绍
1、Session的概念
使用Cookie和附加URL参数都可以将上次请求的状态信息传递到下一次请求中,但是如果传递的状态信息较多,将极大降低网络传输效率和增大服务器端程序处理的难度。Session技术是一种会话状态保存在服务器端的技术,它可以比喻成是医生发给病人的病历卡和医院为每个病人保留的病历档案的结合方式。客户端需要接收、记忆和回送Session的会话标示号,Session可以且通常是借助Cookie来传递会话标示号。
2、Session的跟踪会话机制
Servlet API规范中定义了一个HttpSession接口,HttpSession接口定义了各种管理和操作会话状态的方法。HttpSession对象是保持会话状态信息的存储结构,一个客户端在WEB服务器端对应一个各自的HttpSession对象。Web服务器并不会在客户端开始访问它时就创建HttpSession对象,只有客户端访问某个能与客户端开启会话的Servlet程序是,Web应用程序才会创建一个与该客户端对应的HttpSession对象。Web 服务器为HttpSession对象分配一个独一无二的会话标示号,然后在响应消息中将这个会话标示号传递给客户端。客户端需要记住会话标示 号,并在后续的每次访问请求中都把这个会话标示号传送给Web服务器,Web服务器程序依据回传的会话标示号就知道这次请求的客户端发出的,从而选择与之 对应的HttpSession对象。
3、Session的跟踪机制
Web 应用程序创建与某个客户端对应的HttpSession对象后,只要没有超出一个限定的空闲时段,HttpSession对象就驻留在Web 服务器内存之中,该客户端此后访问任意的servlet程序时,它们都使用与客户端对应的那个已存在的Httpsession对象。HttpSession 接口中专门定义了一个SetAttribute方法将对象存储到HttpSession对象中,还定义了一个 getAttribute方法来检索存储在Httpsession对象中的对象,存储进Httpsession对象中的对象可以被属于同一个会话的各个请 求的处理程序共享。Session是实现网上商城的购物车的最佳方案,存储在某个客户Session中的一个集合对象就可充当给客户的一个购物车。
4、Session的超时管理
Web服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,所以,即使客户已经离开或关闭了浏览器,Web服务器还要保留与之对应的Httpsession对象。随着时间的推移而不断增加新的访问客户端,Web服务器内存中将会因此积累起大量的不断不在使用的Httpsession对象,并将最终导致服务器内存耗尽。Web服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求,Web服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的Httpsession对象变成垃圾。如果客户端浏览器超时后再发出访问请求,Web服务器则认为这是一个新的会话开始,将为之创新的HttpSession对象和分配新的会话标示号。
session的使用
session中存储数据:
String username = request.getParameter("username");
HttpSession session = request.getSession();
System.out.println(session.getId());
session.setAttribute("username", username);
session中得到数据:
HttpSession httpSession = request.getSession();
String username = (String)httpSession.getAttribute("username");
session的原理
我们创建一个项目来分析session的原理:
一、创建一个主页index.jsp:
<form action="ContractListServlet" method="get">
username: <input type="text" name="username"/><br>
<input type="submit" value="submit">
</form>
清除浏览器所有cookie,访问url:http://localhost:8080/SessionTest/
详细的请求头部:
GET /SessionTest/ HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
详细的响应头部:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=5973D26B6164CDDAFF190965C0B4677C; Path=/SessionTest/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 418
Date: Tue, 15 Mar 2016 10:25:12 GMT
保存在浏览器的cookie:
说明:
- 当我们清除cookie,向tomcat服务器发送请求时,浏览器首先会检查是否存在cookie文件(因为我们已经清除了cookie,所以找不到cookie)。第一次访问,没有cookie,直接发送请求。
- tomcat服务器发现请求中没有cookie头部,于是为用户创建一个sessionid,用作标识这个用户的会话,并且在返回给用户的响应中增加了cookie的头部信息,该cookie的path为该项目的上下文/SessionTest。
- 浏览器接收响应,检查响应,发现cookie的头部,把cookie保存起来
- 当cookie还存在时,(也就是人们常说的再次请求)浏览器检查自身保存的cookie,如果host与path都符合。那么在请求的头部增加该符合的cookie信息
- tomcat服务器接收到该cookie,得到cookie中的JSESSIONID的值与先前保存的sessionid做比较,如果一致,则服务器视为是同一个会话
二、创建ContractListServlet,以响应index.jsp的提交
String username = request.getParameter("username");
HttpSession session = request.getSession();
System.out.println(session.getId());
session.setAttribute("username", username);
Cookie cookie = new Cookie("JSESSIONID", "123456");
cookie.setPath("/test");
response.addCookie(cookie);
request.getRequestDispatcher("/list.jsp").forward(request, response);
填写内容linux,点击提交:url为http://localhost:8080/SessionTest/ContractListServlet?username=linux
详细的请求头部:
GET /SessionTest/ContractListServlet?username=linux HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/SessionTest/ Cookie: JSESSIONID=5973D26B6164CDDAFF190965C0B4677C Connection: keep-alive
详细的响应头部:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=123456; Path=/test
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 331
Date: Tue, 15 Mar 2016 10:29:25 GMT
保存的cookie:现在有两个了
三、 只要我们访问的url是这样的形式http://localhost:8080/cookiePath/xxx/xx,浏览器都会携带cookie信息去发送请求的:
- localhost是服务器的地 址,
- 8080是服务器的端口,
- cookiePath是cookie的path(图片见上),
由于上述我们已经有了两个cookie,它们的path分别为, /test和/SessionTest,于是测试访问url:http://localhost:8080/test/jjii
虽然报错404,但是cookie信息仍旧在请求当中:
GET /test/jjii HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: JSESSIONID=123456
Connection: keep-alive
关闭浏览器,cookie被自动清除,所以用户再次的请求,浏览器没有找到cookie,会像上述第一次访问一样,请求中没有cookie的头部。
四、 我们改动ContractListServlet的代码,在response中另外再增加两个cookie2:以下是加了之后的代码
Cookie cookie = new Cookie("JSESSIONID", "123456");
cookie.setPath("/test");
Cookie cookie3 = new Cookie("JSESSIONID", "123456");
cookie3.setPath("/SessionTest/");
Cookie cookie2 = new Cookie("df", "456789");
cookie2.setPath("/");
response.addCookie(cookie);
response.addCookie(cookie2);
response.addCookie(cookie3);
再次访问到从头开始访问到url:http://localhost:8080/SessionTest/ContractDetailServlet
详细的请求头部:
GET /SessionTest/ContractListServlet?username=linux HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/SessionTest/ Cookie: JSESSIONID=3EF72ED7EC55DA676714F773E9110DB9 Connection: keep-alive
详细的响应头部:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=123456; Path=/test df=456789; Path=/ JSESSIONID=123456; Path=/SessionTest/ Content-Type: text/html;charset=ISO-8859-1 Content-Length: 321 Date: Tue, 15 Mar 2016 12:04:00 GMT
浏览器中的cookie有三条:
- name: JSESSIONID, content: 123456, path: /test
- name: df, content: 456789, path: /
- name: JSESSIONID, content: 123456, path: /SessionTest/
结果分析:
- 首先浏览器请求时,会携带cookie头部的:JSESSIONID=5DA63C198B1BBF3930A3CE7EC8613207
- 然后在返回的时候,在响应头部加了三个cookie信息,由于cookie3的名字与路径都与tomcat服务器默认返回的cookie一致,所以导致了该cookie被代码中的cookie3覆盖
五、接着上面的程序,我们添加list.jsp到ContractDetailServlet的请求:http://localhost:8080/SessionTest/ContractDetailServlet
详细的头部请求:
GET /SessionTest/ContractDetailServlet HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/SessionTest/ContractListServlet?username=linux Cookie: JSESSIONID=123456; df=456789 Connection: keep-alive
详细的头部响应:
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Set-Cookie: JSESSIONID=D0ECF2D2EF3946CBBB34BC7E4A426D94; Path=/SessionTest/; HttpOnly Content-Length: 0 Date: Tue, 15 Mar 2016 12:06:19 GMT
浏览器中的cookie有三条:
- name: JSESSIONID, content: 123456, path: /test
- name: df, content: 456789, path: /
- name: JSESSIONID, content: D0ECF2D2EF3946CBBB34BC7E4A426D94, path: /SessionTest/
结果分析:
- 首先浏览器找到匹配/SessionTest的cookie,找到了cookie2(path /)与cokie3(path /SessionTest/ ),在请求中加入这两个cookie
- tomcat服务器接收到请求,发现cookie的sessionid与自身保存的不一致,于是为用户创建了一个sessionid,并把cookie加入到返回的头部
- 浏览器接收到响应的报文,把cookie保存起来,tomcat服务器发送的cookie覆盖了浏览器原来的cookie3
以上是我个人对了session的理解,不正确的地方,还望大家斧正!
出处: www.cnblogs.com/huhx
格言:你尽力了,才有资格说自己的运气不好。
版权:本文版权归作者huhx和博客园共有,欢迎转载。未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。