原标题:JavaWeb的session及其共享技术
1.什么叫会话
一次会话指的是:就好比打电话,A给B打电话,接通之后,会话开始,直到挂断电话,该次会话就结束了,而浏览器访问服务器,就跟打电话一样,浏览器A给服务器发送请求,访问web程序,该次会话就已经接通,其中不管浏览器发送多少请求(就相当于接通电话后说话一样),都视为一次会话,直到浏览器关闭,本次会话结束。
其中注意,一个浏览器就相当于一部电话,如果使用火狐浏览器,访问服务器,就是一次会话了,然后打开google浏览器,访问服务器,这是另一个会话,虽然是在同一台电脑,同一个用户在访问,但是,这是两次不同的会话。
2.引入cookie和session
思考一个问题,一个浏览器访问一个服务器就能建立一个会话,如果别的电脑,都同时访问该服务器,就会创建很多会话,就拿一些购物网站来说,我们访问一个购物网站的服务器,会话就被创建了,然后就点击浏览商品,对感兴趣的商品就先加入购物车,等待一起付账,这看起来是很普通的操作,但是想一下,如果有很多别的电脑上的浏览器同时也在访问该购物网站的服务器,跟我们做类似的操作呢?服务器又是怎么记住用户,怎么知道用户A购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,不能放入用户B或用户C的购物车内的呢?
这里我们就用cookie和session两种会话跟踪技术来跟踪整个会话。
3.cookie简介
3.1.cookie的工作原理
1)首先浏览器向服务器发出请求。
2)服务器就会根据需要生成一个Cookie对象,并且把数据保存在该对象内。
3)然后把该Cookie对象放在响应头,一并发送回浏览器。
4)浏览器接收服务器响应后,提出该Cookie保存在浏览器端。
5)当下一次浏览器再次访问那个服务器,就会把这个Cookie放在请求头内一并发给服务器。
服务器从请求头提取出该Cookie,判别里面的数据,然后作出相应的动作。
3.2.cookie中的常用方法
Cookie cookie=new Cookie(String name,String value) 构造一个cookie对象
response.addCookie(Cookie cookie) 是将一个cookie对象传入客户端。
request.getCookies() 得到所有的cookie对象
cookie.getName() 得到此cookie对象的名字
cookie.getValue() 得到对应名称的cookie的值
cookie.setMaxAge() 设置过期时间
3.3.案例
1@WebServlet( "/CookieServletDemo1")
2publicclassCookieServletDemo1extendsHttpServlet{
3privatestaticfinallongserialVersionUID = 1L;
4
5/**
6* @seeHttpServlet#HttpServlet()
7*/
8publicCookieServletDemo1(){
9super();
10// TODO Auto-generated constructor stub
11}
12
13/**
14* @seeHttpServlet#doGet(HttpServletRequest request, HttpServletResponse
15* response)
16*/
17protectedvoiddoGet(HttpServletRequest request, HttpServletResponse response)
18throwsServletException, IOException {
19// 创建cookie对象
20// cookie中`存放的数据以键值对存在map 键和值都只能是字符串,不支持中文
21Cookie cookie = newCookie( "username", "zhangsan");
22Cookie cookie1 = newCookie( "password", "1234");
23// 失效时间 以秒为单位
24cookie.setMaxAge( 60* 60);
25response.addCookie(cookie);
26response.addCookie(cookie1);
27}
28
29/**
30* @seeHttpServlet#doPost(HttpServletRequest request, HttpServletResponse
31* response)
32*/
33protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response)
34throwsServletException, IOException {
35// TODO Auto-generated method stub
36doGet(request, response);
37}
38
39}
1@WebServlet( "/CookieServletDemo2")
2publicclassCookieServletDemo2extendsHttpServlet{
3privatestaticfinallongserialVersionUID = 1L;
4
5/**
6* @seeHttpServlet#HttpServlet()
7*/
8publicCookieServletDemo2(){
9super();
10// TODO Auto-generated constructor stub
11}
12
13/**
14* @seeHttpServlet#doGet(HttpServletRequest request, HttpServletResponse
15* response)
16*/
17protectedvoiddoGet(HttpServletRequest request, HttpServletResponse response)
18throwsServletException, IOException {
19// 从请求头中获取cookie信息
20Cookie[] cookies = request.getCookies();
21for(Cookie c:cookies){
22System.out.println(c.getName()+ "===="+c.getValue());
23}
24}
25
26/**
27* @seeHttpServlet#doPost(HttpServletRequest request, HttpServletResponse
28* response)
29*/
30protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response)
31throwsServletException, IOException {
32// TODO Auto-generated method stub
33doGet(request, response);
34}
35
36}
3.4.浏览器中查看cookie
不同的浏览器略有差别,这里以谷歌浏览器为例。
F12打开开发者工具 —点击Application选项—选中其中的cookie—选择相应的站点—看到该站点中的所有cookie信息。
3.5.cookie的应用场景
cookie的应用场景有很多,最具代表性的当属网站的记录用户账号和密码的功能了,大家可能经常看到登录某某论坛,某某网站时,下面有个选项为N天内自动登录,其实这就是cookie的应用。当用户第一次输入账号密码时给服务器发送请求时,服务器会根据账号密码回写一个字符串cookie,当用户下次再向该服务器发送登录请求时,则带着这个字符串cookie一起去访问服务器,这时,服务器只需要对比次字符串和数据库中存储的字符串是否相同,则可以达到用户自动登录功能。
3.6.cookie的局限性
Cookie数量和长度的限制。每个站点最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
cookie中只能存字符串。且不支持中文
cookie不适合保存敏感数据(例如密码)可见的
4.session
4.1.session的工作原理
1)浏览器发出请求到服务器。
2)服务器会根据需求生成Session对象,并且给这个Session对象一个编号,一个编号对应一个Session对象
3)服务器把需要记录的数据封装到这个Session对象里,然后把这个Session对象保存下来。
4)服务器把这个Session对象的编号放到一个Cookie里,随着响应发送给浏览器
5)浏览器接收到这个cookie就会保存下来
6)当下一次浏览器再次请求该服务器服务,就会发送该Cookie
7)服务器得到这个Cookie,取出它的内容,它的内容就是一个Session的编号!!!
8)凭借这个Session编号找到对应的Session对象,然后利用该Session对象把保存的数据取出来!
4.2.session的常用方法
4.3.案例
1@WebServlet( "/SeesionServletDemo1")
2publicclassSeesionServletDemo1extendsHttpServlet{
3privatestaticfinallongserialVersionUID = 1L;
4
5/**
6* @seeHttpServlet#HttpServlet()
7*/
8publicSeesionServletDemo1(){
9super();
10// TODO Auto-generated constructor stub
11}
12
13/**
14* @seeHttpServlet#doGet(HttpServletRequest request, HttpServletResponse
15* response)
16*/
17protectedvoiddoGet(HttpServletRequest request, HttpServletResponse response)
18throwsServletException, IOException {
19
20// 创建session对象
21HttpSession session = request.getSession();
22System.out.println(session.getId());
23
24session.setAttribute( "name", "zhangsan");
25
26session.setAttribute( "student", newStudent( 1, "zhangsan", 12));
27Student stu = (Student) session.getAttribute( "student");
28
29stu.setName( "lisi");
30
31// 设置过期时间 单位是秒
32// session.setMaxInactiveInterval(2);
33// 直接销毁session 注销登录
34// session.invalidate();
35
36}
37
38/**
39* @seeHttpServlet#doPost(HttpServletRequest request, HttpServletResponse
40* response)
41*/
42protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response)
43throwsServletException, IOException {
44// TODO Auto-generated method stub
45doGet(request, response);
46}
47
48}
1publicclassStudent{
2
3privateInteger id;
4privateString name;
5privateInteger age;
6publicInteger getId(){
7returnid;
8}
9publicvoidsetId(Integer id){
10this.id = id;
11}
12publicString getName(){
13returnname;
14}
15publicvoidsetName(String name){
16this.name = name;
17}
18publicInteger getAge(){
19returnage;
20}
21publicvoidsetAge(Integer age){
22this.age = age;
23}
24publicStudent(Integer id, String name, Integer age){
25super();
26this.id = id;
27this.name = name;
28this.age = age;
29}
30publicStudent(){
31super();
32// TODO Auto-generated constructor stub
33}
34}
1@WebServlet( "/SeesionServletDemo2")
2publicclassSeesionServletDemo2extendsHttpServlet{
3privatestaticfinallongserialVersionUID = 1L;
4
5/**
6* @seeHttpServlet#HttpServlet()
7*/
8publicSeesionServletDemo2(){
9super();
10// TODO Auto-generated constructor stub
11}
12
13/**
14* @seeHttpServlet#doGet(HttpServletRequest request, HttpServletResponse
15* response)
16*/
17protectedvoiddoGet(HttpServletRequest request, HttpServletResponse response)
18throwsServletException, IOException {
19
20// 创建session对象
21HttpSession session = request.getSession();
22
23System.out.println(session.getAttribute( "name"));
24
25Student stu = (Student) session.getAttribute( "student");
26System.out.println(stu.getName());
27
28}
29
30/**
31* @seeHttpServlet#doPost(HttpServletRequest request, HttpServletResponse
32* response)
33*/
34protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response)
35throwsServletException, IOException {
36// TODO Auto-generated method stub
37doGet(request, response);
38}
39
40}
4.4.session的生命周期
session对象生命周期:
session对象什么创建?
执行request.getSession()方法时
session对象什么销毁?
①默认情况下,session对象在30分钟之后服务器自动销毁。
②手动设置session有效时长
void setMaxInactiveInterval(int interval) -以秒为单位。
③手动销毁
void invalidate()
4.5.session在一次会话结束后消失的原因
由于session的使用需要依赖cookie,cookie每次从浏览器端传输session的id到后台,然后查找对应编号的session进行使用,但由于此时的cookie默认的失效时间是一次会话,当一次会话结束后,存放id的cookie对象就消失了,下一次会话访问时就会生成新的id,那存储在原来的session对象中的数据就无法找到了。
4.6.浏览器禁用cookie能否使用session
可以,但需要手动拼接id传过去,例如
1http: //localhost:8080/day06/session.jsp;jsessionid=AE62ECBAAD2CA16DA6AEBF1D1527CD45
jsessionid指的就是session对应的id
4.7.session共享
4.7.1.基于数据库的Session共享
首选当然是大名鼎鼎的Mysql数据库,并且建议使用内存表Heap,提高session操作的读写效率。这个方案的实用性比较强,相信大家普遍在使用,它的缺点在于session的并发读写能力取决于Mysql数据库的性能,同时需要自己实现session淘汰逻辑,以便定时从数据表中更新、删除 session记录,当并发过高时容易出现表锁,虽然我们可以选择行级锁的表引擎,但不得不否认使用数据库存储Session还是有些杀鸡用牛刀的架势。
4.7.2.基于Cookie的Session共享
这个方案我们可能比较陌生,但它在大型网站中还是比较普遍被使用。原理是将全站用户的Session信息加密、序列化后以Cookie的方式, 统一种植在根域名下(如:.host.com),利用浏览器访问该根域名下的所有二级域名站点时,会传递与之域名对应的所有Cookie内容的特性,从而实现 用户的Cookie化Session 在多服务间的共享访问。
这个方案的优点无需额外的服务器资源;缺点是由于受http协议头信心长度的限制,仅能够存储小部分的用户信息,同时Cookie化的 Session内容需要进行安全加解密(如:采用DES、RSA等进行明文加解密;再由MD5、SHA-1等算法进行防伪认证),另外它也会占用一定的带宽资源,因为浏览器会在请求当前域名下任何资源时将本地Cookie附加在http头中传递到服务器。
4.7.3.基于Memcache的Session共享
Memcache由于是一款基于Libevent多路异步I/O技术的内存共享系统,简单的Key + Value数据存储模式使得代码逻辑小巧高效,因此在并发处理能力上占据了绝对优势,目前本人所经历的项目达到2000/秒 平均查询,并且服务器CPU消耗依然不到10%。
另外值得一提的是Memcache的内存hash表所特有的Expires数据过期淘汰机制,正好和Session的过期机制不谋而合,降低了 过期Session数据删除的代码复杂度,对比“基于数据库的存储方案”,仅这块逻辑就给数据表产生巨大的查询压力。
更多资深讲师相关课程资料、学习笔记请入群后向管理员免费获取,更有专业知识答疑解惑。入群即送价值499元在线课程一份。
QQ群号:560819979
敲门砖(验证信息):醉渔唱晚返回搜狐,查看更多
责任编辑: