1、简介
session: 域对象,就是在不同资源之间共享数据
四大域对象:
pageContext,request、session、application
本页面、同一次请求、同一次会话(浏览器打开-关闭)、整个项目(只要服务器不关闭)
session:在同一次会话共享数据。
session.setAttribute(key,value);//设置数据,Object value
Object value = session.getAttribute(key);//获取数据
session.removeAttribute(key);//移除数据的
2、获取session
1)、request.getSession();//获取到session对象
2)、JSP页面有隐含的session对象。我们直接拿来使用
服务器创建session对象。
session每个会话都有自己的session
session在获取的时候,如果是新的会话,服务器会给会话创建一个新的session对象
如果是旧的会话,会只用之前获取到的session
3、session的创建
服务器创建session。
服务器会为每个会话创建他对应的session。在第一次获取session对象的时候才会创建session对象。
4、会话控制原理
1)、HTTP协议是一个无状态的协议。
无法识别多个请求是否有关联关系。
服务器无法识别请求来自于哪个用户。
服务器可能就不知道他创建的session对象应该属于谁的。
第一次获取session对象。没有能标识用户身份的内容
请求-》不能标识用户身份
响应:多了一个字段
服务器命令保存的cookie就是创建的session对象的id值
Set-Cookie: JSESSIONID=D62C83CD3A285840D469C44636849EC0; Path=/13.Session
命令浏览器去保存一个cookie。浏览器就会保存好cookie。
浏览器下次访问会带上这个cookie。
Cookie: JSESSIONID=D62C83CD3A285840D469C44636849EC0
第二次获取session对象。
请求头中多了一个字段:
//浏览器带的这个字段就是session对象的id值
Cookie: JSESSIONID=D62C83CD3A285840D469C44636849EC0
服务器获取session对象
request.getSession();
1、request中带了一个名为JSESSIONID=D62C83CD3A285840D469C44636849EC0的cookie
2、服务器request.getSession();获取session对象会判断
3、服务器取出JSESSIONID的值(表示的是session对象的id值)。
4、服务器就会按照这个id值查找之前创建的所有的session对象,哪个session的id是对应的值,便将它返回。
5、将之前创建的对象返回。
会话控制原理:
1)浏览器获取session对象以用来保存或者获取数据
2)服务器会根据请求中携带的JSESSIONID这个Cookie,来查找对应的session对象
3)找到返回这个session给你用
4)没找到创建一个新的session对象,并且创建还创建了一个Cookie,名叫JESSIONID,值是session对象的id值
5)以后再访问服务器获取session对象。重复步骤2开始
session对象创建:
服务器会为每个会话创建他对应的session。
在第一次获取session对象的时候才会创建session对象。
如果整个项目运行过程中不需要session对象,就不会创建。
5、session对象是创建好默认保存在内存中。
session对象需要销毁。
销毁:
会话关闭(浏览器关闭)需要销毁session。
浏览器关闭服务器并不会销毁session。
session的销毁是服务器做的。
session默认的生存时间。1800秒:代表session在1800秒不使用就会销毁。
在服务器web.xml中
session.getMaxInactiveInterval();
1)第一次发请求获取session,根据JSESSIONID判断。
2)服务器返回一个新的session,命令浏览器保存JSESSIONID这个cookie
Set-Cookie: JSESSIONID=D60840CD71FAC53EACD5B2506C27F1E6
session只有3秒
3)再来获取session。带上JSESSIONID。
Cookie:JSESSIONID=D60840CD71FAC53EACD5B2506C27F1E6
4)根据带来的JSESSIONID寻找session对象的时候没有找到(session3秒后销毁了)
创建了一个新的session对象,响应:Set-Cookie:JSESSIONID=146246FF5A0DE3BBC3ACB6A02FA01CA8;
我们通过下面方法指定session的最大不活动时间,也就是多少秒不使用后过期
负数:session永不过期
0和整数:session多少秒不使用后过期
session.setMaxInactiveInterval(3);
使session立即失效
为什么每次打开浏览器是一次新会话?是session对象没了吗?
session实际要维持30分钟。
这个现象根本原因:不是session没有了,
而是cookie没了。我们保存JSESSIONID这个cookie的时候。cookie默认的生存时间是一次会话,也就是浏览器关闭就没了,
而下次我们要获取session,之前浏览器关闭了,cookie没了,所以获取session的时候。不会携带jSESSIONID这个cookie,
所以服务器会创建新的session。
默认现象创建新session不是因为session对象没了,而是cookie没了。
默认会话期间的cookie其实是保存在浏览器进程中的。
我们也可以持久化保存cookie。cookie才会被保存在硬盘中。
6、浏览器禁用cookie,通过URL重写技术
JSESSIONID=44E065DA42AA2E3FCAD92A279EFF38D3
user=admin
JSESSIONID=1D1EA4DC6E300F695F9115CA7AA52099;新的
1)我们可以通过URL重写的手段来继续带上JSESSIONID
Session/target.jsp;jsessionid=44E065DA42AA2E3FCAD92A279EFF38D3
在url后面分号带上jsessionid=44E065DA42AA2E3FCAD92A279EFF38D3
2)
url重写 路径应该带上项目名
如果浏览器禁用了cookie
encodeURL会在我们要访问的地址后面加上 ;jsessionid=xxx;
如果浏览器没禁用cookie
encodeURL不会去改造访问路径
response.encodeURL(request.getContextPath()+"/target.jsp")
3)标签库中有个标签 c:url 用来重写url地址
因为url重写机制不太安全,使用较少。
7.session活化钝化
1)服务器停止session去哪儿了
钝化:把session从内存序列化到磁盘
1、服务器停止,session以及他里面所有的数据都会序列化到磁盘中。
保存为一个SESSIONS.ser文件。位置在服务器/work/../../自己的项目根目录
2、当大量session存在的时候将一些不经常使用的session先钝化起来。
下次使用的时候再活化
3、当session超过一定不使用时间(30分钟内)后也会钝化。
活化:把session从磁盘反序列化加载到内存。
服务器启动,session会从磁盘反序列化到内存中
钝化后的session对象再次使用就会活化。
对象要能同session一起活化钝化必须实现序列化接口
8、session典型应用。
session.setAttribute(key,value);//在会话域中共享数据
session.getAttribute(key);
1)用户登陆和退出。将用户信息放在session域中。
整个会话期间都能获取到用户数据
2)防止表单重复提交
表单重复提交
1、提交数据以后,直接刷新页面会提交上次请求。
因为转发来到页面,导致浏览器从请求发起到请求完成页面响应到内容,浏览器的地址栏没变。
解决:可以将转发改为重定向。
但是2、3情况不能防止
2、网速慢的情况下,用户不知道,多次点击提交按钮。将同一个请求又提交多次
根本原因是按钮能点击无数次。我们只需要将按钮做成只能点击一次。
var btn = document.getElementById("subBtn");
2、绑定单击事件
btn.onclick = function(){
3、将按钮设置为不可用 submitObject.disabled=true|false
this.disabled = true;//禁用,还会阻止表单提交
4、找到表单,手动提交
var formEle = document.getElementById("form1");
//提交表单
formEle.submit();
};
不能解决问题1、不能解决问题3
3、用户点击后退按钮,回到之前页面,之前的数据还在,再次提交
深入底层分析:
表单重复提交的根本原因。两次请求的内容都是相同的。
1、刷新就是将上次请求再发一遍。所以多次请求都是一模一样的
2、多次点击提交按钮。也是发送相同的请求内容。
3、用户后退,发送的内容和上几次都是一样的。
HTTP协议是一个无状态协议。
服务器无法识别上次的请求和这次的请求是否同一请求(请求里面的所有东西都一样)。
只要服务器知道两次请求是同一个请求即可。如果第二次请求过来和上次的是一模一样的,
服务器就可以拒绝处理
如何让服务器知道两次请求是同一请求。
令牌机制
虎符:
两半。
皇帝手中一半
将军手中一半
将军必须两半和一起你对比成功才能调兵遣将。
我们也可以创建一个令牌。
可以创建两份。
浏览器交一份
服务器交一份
每次提交请求,浏览器可以带上她的令牌,服务器处理请求之前验证浏览器带的令牌,是不是正确的。
如果正确则处理请求,否则拒绝处理。
表单重复提交多次,每次的数据都是一模一样的。(根据重复提交的特点);
1)访问页面的时候可以创建两个令牌。这两个令牌一模一样。给浏览器一份,给服务器一份
2)浏览器访问服务器提交表单的时候带上她的令牌
3)服务器处理请求之前先看一看令牌。如果和自己的一样就处理请求, 服务器令牌一但用过一次立即作废
4)以后重复提交表单的时候令牌也是上次的,而服务器的令牌已经变了,验证失败就不能提交数据