Cookie和Session详解
Cookie学习
Cookie由w3c组织提出,是属于Http扩展协议的一部分。
Cookie实际上是一小段文本信息,服务器如果需要记录客户端的身份,就
保存一个cookie在客户端(通过设置响应头的方式),当浏览器再次请求该网站时,浏览器就会把请求的网址
和保存的cookie再发送给服务器(通过设置请求头的方式),服务器检查cookie,来辨认用户状态。
Cookie的大小限制
http协议规定
>1个cookie最大为4kb
>一个服务器最多向一个浏览器保存20个cookie
>一个浏览器最多可以保存300个cookie
每个浏览器都会在一定范围内违反http规定,比如cookie大小和保存cookie的个数都会有所不同。
Cookie的用途
服务器使用cookie来跟踪客户端状态。
简单的例子,一个咖啡店每买五杯咖啡就赠送一杯,咖啡店给你一个卡片,卡片上有盖的章,你下次来的话通过这个卡片就知道你买过几杯咖啡,这个卡片就是Cookie。
--每个cookie就是一个键值对。
javaweb中使用cookie
-原始方法
使用response发送 set-Cookie响应头
使用request获取Cookie响应头
-便捷方法
使用response.addCookie()方法向浏览器保存cookie
使用request.getCookies()方法获取浏览器保存的cookie
案例一
案例:a.jsp页面保存cookie,b.jsp页面获取cookie
a.jsp
<body>
<h1>保存Cookie</h1>
<%
Cookie c1=new Cookie("name","zhangsan"); //创建Cookie
Cookie c2=new Cookie("age","18");
response.addCookie(c1); //向客户端保存Cookie
response.addCookie(c2);
%>
</body>
b.jsp
<body>
<h1>获取Cookie</h1>
<%
Cookie[] cookies=request.getCookies();
for(Cookie c:cookies)
{
String name=c.getName(); //获取cookie的键
String value=c.getValue(); //获取cookie的值
out.print(name+"="+value);
}
%>
</body>
Cookie生命周期
Cookie的maxAge属性:cookie的最大生命,即Cookie可保存的最大时长,以秒为单位。
Cookie.setMaxAge(秒数)
通过setMaxAge设置cookie存在时长表示这个cookie会被浏览器保存到硬盘上,不设置的话
默认cookie保存在内存中,浏览器一关闭cookie就消失。
->maxAge>0:浏览器会把cookie保存到客户机硬盘上,有效时长由maxAge值决定
->maxAge<0:cookie只在浏览器内存中存在,当用户关闭浏览器时,浏览器进程结束,cookie死亡。
->maxAge=0:浏览器会删除这个cookie。
Cookie的path(路径)
!!!Cookie的path不是设置这个Cookie在客户端的保存路径。
Cookie的path由服务器创建Cookie时设置。
当浏览器访问服务器某个路径时,我们需要把哪些cookie传递归还给服务器呢?这就由cookie的path决定。
浏览器访问的路径如果包含某个cookie路径,就把该cookie归还给服务器。
通过Cookie.setPath()设置路径。
例如:aCookie.path=/CookieTest/; bCookie.path=/CookieTest/Test/; cCookie.path=/CookieTest/Test/A/;
--访问/CookieTest/index.jsp时,归还 aCookie.
--访问/CookieTest/Test/a.jsp时,归还 aCookie 和 bCookie。
--访问/CookieTest/Test/A/b.jsp时,归还 aCookie 和 bCookie 和 cCookie.
Cookie的path默认值:当前访问路径的父路径。
Session学习
Session在计算机中,常被理解为为会话。
http协议是无状态的,也就是此次连接无法得到上次连接的状态
因此web应用开发就出现了保持http连接状态的技术,Cookie和Session。
会话:一个用户对服务器的多次连贯性请求,所谓连贯性请求,就是多次请求之间没有关闭浏览器。
比如打电话时从拿起电话拨号到挂断电话就是一个Session。
会话范围:用户从首次访问服务器开始,到关闭浏览器结束。
服务器会为每个客户端创建一个session对象,然后被服务器保存到Map集合中,这个Map集合被称为session缓存。
HttpSession
-HttpSession是由javaweb提供的,对session机制的实现规范,用来实现会话跟踪(Session)的接口。
-session是服务器端对象,保存在服务器端。
-HttpSession底层依赖Cookie,或者是URL重写。
HttpSession是Servlet三大域对象(Request,Session,application(ServletContext))之一。
-常用方法
*setAttribute() //设置属性
*getAttribute() //获取属性
*removeAttribute() //删除属性
-servlet中获取session对象,HttpSession session=request.getSession()
-jsp中session是内置对象,可以直接使用。
案例一
案例:第一个页面往session里面设置值,第二个页面获取session里的值,总共是两个请求。
第一个页面
<body>
<h1>设置Session内容</h1>
<%
session.setAttribute("name", "张三");
%>
</body>
第二个页面
<body>
<h1>获取session内容</h1>
<%
String s=(String)session.getAttribute("name");//获取session值
%>
<%=s %>
</body>
案例二
需求:写一个登陆系统,登陆成功时显示登陆成功,失败时提示用户名或者密码错误。
登陆页面 Login.jsp
<body>
<h1>登陆页面</h1>
<form action="/SessionTest/LoginServlet" method="post">
用户名:<input type="text" name="username"><br/>
密 码:<input type="password" name="password"><br/>
<input type="submit" value="登陆">
</form>
<!-- 获取错误信息 -->
<%
String message="";
String msg=(String)request.getAttribute("msg");
if(msg!=null)
{
message=msg;
}
%>
<!--显示信息-->
<font color="red">
<%=message %>
</font>
</body>
判断登录名和密码是否正确的Servlet
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); //设置编码
String name=request.getParameter("username"); //获取账号密码
String passwd=request.getParameter("password");
if((name.equals("cuiandong"))&&(passwd.equals("123456"))) //判断账号密码
{
HttpSession hs=request.getSession(); //把用户名存到session中
hs.setAttribute("user", name);
response.sendRedirect("/SessionTest/session2/success.jsp");//跳转到成功页面
}
else
{
request.setAttribute("msg", "用户名或密码错误"); //错误的话把错误信息存到request域中,并转发回登陆页面
request.getRequestDispatcher("/session2/Login.jsp").forward(request, response);
}
}
}
成功页面 success.jsp
<body>
<!-- 判断是否登陆,否则无法进到该页面 -->
<%
String name=(String)session.getAttribute("user");
//如果session为空,则说明没有登陆成功,则不能访问该页面,返回到登陆页面
if(name==null)
{
request.setAttribute("msg", "请您先登陆");
request.getRequestDispatcher("/session2/Login.jsp").forward(request, response);
return;
}
%>
登陆成功,<%=name %>
</body>
session原理
当客户端首次请求访问服务器时,服务器首先检查客户端的请求里是否包含
sessionid,如果已包含一个sessionid,则说明服务器已经为该客户端创建过session,服务器就通过
这个sessionid找到该服务端对应的session,如果不包含sessionid,则为此客户端创建一个session
并且生成一个sessionid,通过cookie的方式传给客户端。
当浏览器关闭时,sessionid这个cookie就会销毁,但是服务器里的session并没有消失
当session不用的时间超过最大不活动时间时,服务器将清理session。
tomcat设置的最大不活动时间为30分钟。
一个常见的误区是客户端访问服务器时session就会被创建,这样会大量消耗服务器资源。
事实是服务器在第一次获取session时,也就是调用request.getSession()时,才会创建session。
当第一次调用request.getSession()方法时
(1)首先获取Cookie中的session id
-如果sessionid不存在,创建session,把session保存起来,把新创建的sessionid保存到cookie中。
-如果sessionid存在,则通过sessionid查找对应的session对象,如果没有查找到,则创建和保存session,把新创建的sessionid保存到cookie中。
-如果sessionid存在,通过sessionid查找到了对应的session对象,那么就可以直接使用session。
(2)返回session对象
request.getSession()和request.getSession(true)效果是一样的,都是执行上面的流程。
request.getSession(false)则当sessionid不存在或者sessionid存在但是session对象不存在时,返回null,而不会创建session对象。
有的人发现,就算jsp页面中没有使用request.getSession()方法,服务器也会保存一个sessionid到客户端。
这是因为JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。
HttpSession的其他方法
-String getId():获取sessionid
-int getMaxInactiveInterval():获取session最大不活动时间。tomcat默认为30分钟,当session30分钟不活动,服务器将清理session。
-void invalidate():让session失效。当session失效后,客户端再次请求,服务器会创建新的session和sessionid。
实现登陆退出功能时,就可以调用此方法。
配置session的最大不活动时间
在web.xml中
<session-config>
<session-timeout>30</session-timeout>
</session-config>
URL重写
session依赖cookie,目的是客户端请求时需要sessionid,这样才能找到对应的session。
当客户端禁用cookie时,就无法得到sessiodid。
这时候可以把sessionid附加在所有页面的url上,这样当用户请求页面时
sessionid会作为请求体的一部分发送回服务器,这种方法就叫做url重写。
例如:
<body>
<a href="/SessionTest/LoginServlet;JSESSIONID=<%= session.getId() %>">点击这里</a>
</body>
注意是每个页面都需要加上sessionid参数。
但这是浏览器cookie被禁用的情况下的方法,怎么判断客户端浏览器cookie是否被禁用呢?
可以使用response.encodeURL(“需要加sessionid的路径”) 例如:response.encodeURL("/SessionTest/LoginServlet")
这个方法会查看cookie是否存在,如果不存在,就在指定的url后面添加JSESSIONID参数。
如个存在,就不会在url后面添加任何东西。
<link rel="stylesheet" href="http://csdnimg.cn/release/phoenix/production/markdown_views-d4dade9c33.css">
</div>