会话跟踪技术
在 JavaWeb 项目中浏览器向服务器发送第一个请求开始,会话就已经开始了,直到浏览器关闭,会话结束;
会话跟踪技术就是:在一个会话中的多个请求中共享数据.
1.CooKie技术
Http的协议是无状态协议,也就是每个请求都是独立的,不记录前一次请求的状态,所以在Http协议中可以使用Cookie技术来完成会话跟踪
Cookie是一个键和一个值组成,随着服务器的响应发送给浏览器.然后浏览器将CooKie保存起来,当下一次再访问服务器时把CooKie再发送给服务器
CooKie是不能跨浏览器的
CooKie中不能存在中文
CooKie的用途:
1.服务器使用CooKie来跟踪客户端状态
2.保存购物车信息
3.显示上次登录名
...
CooKie与HTTP头
CooKie是通过HTTP的请求和响应头在客户端和服务器端传递的
CooKie:
请求头,客户端发送给服务器端
格式:CooKie:a=A;b=B;c=C //多个CooKie用分号隔开
Set-Cookie:
响应头,服务器端发送给客户端
一个CooKie对象一个Set-Cookie:
Set-CooKie:a=A
Set-Cookie:b=B
Set-Cookie:c=C
CooKie覆盖
如果服务器端发送重复的CooKie,那么会覆盖原本的CooKie.
JavaWeb中使用Cookie
原始做法:
使用response发送Set-Cookie响应头
使用request获取CooKie请求头
便捷方法:
使用response.addCooKie()方法向浏览器保存CooKie
使用request.getCooKies()方法获取浏览器返还的Cookie
例子1:
一个jsp保存cookie a.jsp
一个jsp获取浏览器归还的cookie b.jsp
//a.jsp
<html>
<head>
<title>保存Cookie</title>
</head>
<body>
<%
Cookiecookie1=newCookie("aaa","AAA");
response.addCookie(cookie1);
Cookiecookie2=newCookie("bbb","BBB");
response.addCookie(cookie2);
%>
</body>
</html>
//b.jsp
<html>
<head>
<title>获取Cookie</title>
</head>
<body>
<%
Cookie[]cookies=request.getCookies();
if(cookies!=null) {
for(Cookiec:cookies) {
out.print(c.getName()+"="+c.getValue()+"<br/>");
}
}
%>
</body>
</html>
例子2:
//把数据传给CooKie
Cookiecookie=newCookie("username",username);
//把数据写回浏览器
resp.addCookie(cookie);
Stringusername=null;
//获取浏览器带过来的数据
Cookie[]cookies=req.getCookies();
for(Cookiecookie:cookies) {
if("username".equals(cookie)) {
username=cookie.getValue();
}
}
欢迎: ${cookie.username.value}<br>
使用${cookie.username.value} 可以不用在servlet再获取username的值;节省了数以万计的代码,更简洁
但是因为传递机制的问题,在登录后的第一个页面,使用这种方法会找不到cookie.username.value 值的问题,只能从servlet中req.setAribute("username",username) 进行获取
修改cookie
有两种方式:
1> 修改指定Cookie的值
Stringusername=null;
Cookie[]cookies=req.getCookie();
for(Cookiecs:cookies){
Stringname=cs.getName();
if("username".equals(name)){
username=cs.getValue();
cs.setValue("xiaoming");
resp.addCookie(cookie);
req.Attribute("username",username);
}
}
2> 新建Cookie用来覆盖原先的Cookie
Cookiecookie=newCookie("username","xiaoming");
resp.addCookie(cookie);
设置Cookie的存活时间
Cookie对象的 setMaxAge(int expiry)
setMaxAge(60); 设置存活时间 60 秒 单位为秒
setMaxAge(0); 设置为立即消除当前Cookie对象
setMaxAge(-1); 会话Cookie 浏览器关闭即销毁
Cookie存在浏览器中,默认情况下都为会话Cookie 浏览器关闭即消除
按照分类可分为持久性Cookie 和 非持久性Cookie
持久性Cookie存在磁盘中,只有用户手动消除或者到期才被删除
非持久性Cookie存在内存中,浏览器关闭就消失,存在时间短暂
//创建Cookie的时候设置存活时间
Cookiecookie=newCookie("username",username);
cookie.setMaxAge(60);//设置无操作60秒后自动销毁Cookie对象
cookie.serMaxAge(0);//设置立即销毁当前Cookie对象
cookie.setMaxAge(-1);//设置会话Cookie 浏览器关闭即销毁
resp.addCookie(cookie);
删除Cookie
设置setMaxAge(0)即可
Stringusername=null;
Cookie[]cookies=req.getCookie();
for(Cookiecs:cookies){
if("username".equals(cs.getName())){
cs.setMaxAge(0);
resp.addCookie(cs);
break;
}
}
cookie的中文问题
在TomCet8.5以下的Cookie中 name属性和value属性都不支持中文,如果有中文必报500状态
在TomCet8.5以后的版本则不需要手动解决;
TomCet8.5以下 中文解决思路:
URLEncoder类 encode("中文","UTF-8");方法 把中文字符转换为非中文
URLDecoder类 decode("非中文","UTF-8"); 方法 把非中文转化为中文
//往Cookie中存中文
Cookiecookie=Cookie("小明",URLEncode.encode("UTF-8"));
//获取Cookie中的中文
Cookie[]cookies=req.getCookies();
for(Cookiecs:cookies){
if("useranem".equles(cs.getName)){
URLDecode.decode(cs.getValue(),"UTF-8");
}
}
Cookie 域/路径
1.作用
为了浏览器能够识别Cookie发送到对应的服务器,以及识别哪些请求要携带Cookie,默认Cookie都带了服务器的标识以及需要携带Cookie的资源标识,这是出于安全的考虑,为了保护Cookie不被带到别的服务器里去
2.域
用来识别服务器,包含IP : 端口或域名:端口 , 可通过Cookie对象的setDomian方法设置.
默认的Cookie中的域是创建Cookie的服务器的域名.域名分类:
1.一级域名: (比如) baidu.com
2.二级域名: (比如) map.baidu.com
3......
若想在相同的主域名中共享Cookie资源,之需要设置Cookie的domain即可,若主域名不同则无法共享资源
cookie.setDomain(".baidu.com");
3.路径
用来识别资源,可通过Cookie对象的setPath设置,默认是创建Cookie的资源的路径
(比如:) /cookie/index 则Path则为/cookie,访问带cookie开头的资源都会携带该Cookie
如果想在使用的页面都带上Cookie 设置setPath为"/" 即可 此时/下的页面都会携带该Cookie资源
总结:
若主域不同,不管Path如何都不会共享cookie资源
若主域相同,且path为"/" 则访问该域下的任意资源都会携带该域的Cookie
Cookie问题和应用场景
应用场景:
存用户的标识,解决无状态问题
登录时记住名字
未登录时实现购物车
存在的问题:
1.单独使用的电脑没什么问题,如果是公用的电脑则存在安全问题
2.存数据TomCet8.5以内的比较麻烦,(编码,解码)
3.一个Cookie只能设置一个值,值须字符串类型
4.一台服务器的在一个客户端存储的Cookie大小,数量有限
Cookie大小限制在4K
同一个服务器只能在客户端最多只能存20个cookie
一个浏览器最多只能存300个cookie
2.Session
Session 是服务器端会话跟踪技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的Session对象
Session对象由服务器端创建
Session存在服务器中
Session对象在用户第一次访问服务器端资源时创建
Session对象中数据的传递 浏览器 -> 服务器(Session) -> 数据在服务器
服务器如何识别不同的Session?
浏览器 -> 服务器(Session) sessionId
浏览器sessionId -> 服务器
Session其底层依然需要依赖Cookie来传递sessionId ,存sessionId的Cookie为会话Cookie
因此Session在浏览器关闭后就无法进行使用了,原因是sessionId丢失,服务器将会在30分钟后销毁所有未有操作的Session对象
Session的基本API
1.获取Session
HttpSeervletRequest 的API
getSession(true) 判断是否存在Session ,存在则获取,不存在则创建新的Session对象返回
getSession(false) 判断是否存在Session,存在则获取,不存在则返回null
getSession() 判断是否存在Session(浏览器是否携带sessionId),存在则取出,不存在则创建新的Session对象
推荐使用getSession() 满足需求的同时 简洁
2.Session数据共享
HttpSession 的 API:
setAttribute(String name,Object value) 设置属性名和属性值
getAttribute(String name) 通过属性名获取属性值
removeAttribute(String name) 从Session中移除指定的属性名和属性值
invalidate() 移除整个Session对象 删除所有的属性和属性值
往Session中存入数据
Stringusername=req.getParameter("username");
HttpSessionsession=req.getSession();
session.setAttribute("USER_IN_SESSION",username);
获取Session的数据
Stringusername=null;
HttpSessionsession=req.getSession();
username=(username)session.getAttribute("USER_IN_SESSION");
req.setAttribute("username",username);
因为Session运行在服务器端 , jsp也运行在服务器端,所以jsp中可以直接获取
username = ${USER_IN_SESSION}
移除Session中的元素
//获取Session
HttpSessionsession=req.getSession("USER_IN_SESSION");
//移除Session中指定元素
session.removeAttribute("USER_IN_SESSION");
销毁整个Session
//获取Session
HttpSessionsession=req.getSession("USER_IN_SESSION");
//销毁整个Session
session.invalidate();
Session细节使用
Session超时管理
设置会话的有效时间
全局修改:
在TomCet的web.xml中的
设置保存多少分钟
局部修改:
在创建Session的servlet中设置
session.setMaxInactiveInterval( 3 ); // 设置只保存 3 分钟
Session的使用规范
一般设置为 XXX_IN_SESSION 且这个属性名是唯一的
session.setAttribute("XXX_IN_SESSION",值);
session中可以存放多个数据,若数据是有联系的,比如用户名和密码, 我们会分装成一个对象再存到Session中