Cookie 和 Session
Posted qqiua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cookie 和 Session相关的知识,希望对你有一定的参考价值。
在Web应用中,一个客户端(浏览器)与Web服务器之间连续发生的一系列请求和响应的过程称为一个会话(如一个用户在某购物网站上的整个购物过程就是一个会话)。在整个会话过程中,客户端与服务器端的交互会产生一些数据,而Web服务器需要对这些数据进行保存。在Servlet技术中,主要提供两个用于保存会话数据的对象,分别是Cookie和Session。
1 Cookie 对象
Cookied主要用于将会话保存到用户的浏览器中,从而使浏览器和服务器可以更好地进行数据交互。
Cookie是浏览器端使用的一种记录用户状态的机制,它实际上是一小段保存在浏览器中的文本信息。当客户端通过浏览器请求服务器时,如果服务器需要记录该用户的状态,就会使用response对象向客户端浏览器颁发一个Cookie,客户端浏览器会把Cookie保存起来。当通过浏览器再次请求该网站时,浏览器会把请求的网址连同该Cookie一同提交给服务器,服务器会检查该Cookie,以此辨认用户状态。
服务器向客户端发送Cookie时,会在HTTP响应头字段中增加Set-Cookie响应头字段。语法格式:
Set-Cookie: user=admin; path=/;
user:表示Cookie名称;
admin: 表示Cookie的值;
Path:表示Cookie的属性
Cookie在浏览器和服务器之间的传输过程如下图:
当用户第一次通过浏览器访问服务器时,服务器会在响应消息中加入Set-Cookie头字段,将用户信息以Cookie的形式发给浏览器。用户浏览器接收了服务器发送的Cookie信息,就会将它保存在浏览器的缓冲区中,这样,当浏览器后续访问该服务器时,会在请求消息中将用户信息以Cookie的形式发送给Web浏览器,从而使服务器端分标出当前请求是由哪个用户发出的。
1.1 Cookie API
Java中的javax.servlet.http.Cookie类用于创建一个Cookie
Cookie类的主要方法 |
|||
No. |
方法 |
类型 |
描述 |
1 |
构造方法 |
实例化Cookie对象,传入Cookie名称和Cookie的值 |
|
2 |
public String getName() |
普通方法 |
用于返回Cookie的名字 |
3 |
public String getValue() |
普通方法 |
用于返回Cookie的值 |
4 |
public void setValue(String newValue) |
普通方法 |
用于为Cookie设置一个新的值 |
5 |
public void setMaxAge(int expiry) |
普通方法 |
用于设置Cookie子浏览器客户机上保持有效的秒数。即Cookie的有效期,当服务器给浏览器回送一个Cookie时,如果在服务器端没有调用setMaxAge方法设置Cookie的有效期,那么Cookie的有效期只在一次会话过程中有效,用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一次会话,当用户关闭浏览器,会话就结束了,此时Cookie就会失效,如果在服务器端使用setMaxAge方法设置了Cookie的有效期,比如设置了30分钟,那么当服务器把cookie发送给浏览器时,此时Cookie就会在客户端的硬盘上存储30分钟,在30分钟内,即使浏览器关了,Cookie依然存在,在30分钟内,打开浏览器访问服务器时,浏览器都会把Cookie一起带上,这样就可以在服务器端获取到客户端浏览器传递过来的Cookie里面的信息了,这就是Cookie设置maxAge和不设置maxAge的区别,不设置maxAge,那么Cookie就只在一次会话中有效,一旦用户关闭了浏览器,那么Cookie就没有了,那么浏览器是怎么做到这一点的呢,我们启动一个浏览器,就相当于启动一个应用程序,而服务器回送的Cookie首先是存在浏览器的缓存中的,当浏览器关闭时,浏览器的缓存自然就没有了,所以存储在缓存中的Cookie自然就被清掉了,而如果设置了Cookie的有效期,那么浏览器在关闭时,就会把缓存中的cookie写到硬盘上存储起来,这样Cookie就能够一直存在了。 |
6 |
public int getMaxAge() |
普通方法 |
用于返回Cookie子浏览器客户机上保持有效的秒数 |
7 |
public void setPath(String uri) |
普通方法 |
设置Cookie的有效路径,比如把Cookie的有效路径设置为"/xdp",那么浏览器访问"xdp"目录下的web资源时,都会带上Cookie,再比如把cookie的有效路径设置为"/xdp/gacl",那么浏览器只有在访问"xdp"目录下的"gacl"这个目录里面的web资源时才会带上Cookie一起访问,而当访问"xdp"目录下的web资源时,浏览器是不带cookie的 |
8 |
public String getPath() |
普通方法 |
获取Cookie的有效路径 |
9 |
public void setDomain(String pattern) |
普通方法 |
设置Cookie的有效域 |
10 |
public String getDomain() |
普通方法 |
获取Cookie的有效域 |
1.2 示例: 显示用户上次访问的时间
1 package cn.cookie;
2 import java.io.IOException;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 import javax.servlet.ServletException;
6 import javax.servlet.http.Cookie;
7 import javax.servlet.http.HttpServlet;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10
11 public class cookie1 extends HttpServlet {
12 private static final long serialVersionUID = 1L;
13 public void doGet(HttpServletRequest request, HttpServletResponse response)
14 throws ServletException, IOException {
15 //设置服务器端以UTF-8编码进行输出
16 response.setCharacterEncoding("UTF-8");
17 //设置浏览器以UTF-8编码进行接收,解决中文乱码问题
18 response.setContentType("text/html; charset=UTF-8");
19 String lastAccessTime=null;
20 Cookie[] cookies = request.getCookies();
21 for(int i=0; cookies!=null && i<cookies.length; i++){
22 if("lastAccess".equals(cookies[i].getName())){
23 lastAccessTime = cookies[i].getValue();
24 break;
25 }
26 }
27 if(lastAccessTime == null){
28 response.getWriter().print("您是首次访问本站");
29 }else{
30 response.getWriter().print("您上次访问的时间是:"+lastAccessTime);
31 }
32 //创建cookie,将当前时间作为cookie的值发送给客户端
33 String currentTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
34 Cookie cookie = new Cookie("lastAccess", currentTime);
35 response.addCookie(cookie);
36 }
37 public void doPost(HttpServletRequest request, HttpServletResponse response)
38 throws ServletException, IOException {
39
40 }
41 }
第一次访问,运行结果:
刷新后:
在上面的例子中,在程序代码中并没有使用setMaxAge方法设置cookie的有效期,所以当关闭浏览器之后,cookie就失效了,要想在关闭了浏览器之后,cookie依然有效,那么在创建cookie时,就要为cookie设置一个有效期。
在34行后添加如下代码:
//设置Cookie的有效期为1天
cookie.setMaxAge(24*60*60);
这样即使关闭了浏览器,下次再访问时,也依然可以通过cookie获取用户上一次访问的时间。
1.3 Cookie注意细节
(1)一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。
(2)一个Web站点可以给有个Web浏览器发送多个Cookie,一个Web浏览器也可以存储多个Web站点提供的Cookie。
(3)浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4kb。
(4)如果创建了一个cookie,并将他发送给浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器中),用户推出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAges,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
1.4 Cookie中存取中文
要想在cookie中存储中文,那么必须使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码,例如:
1 Cookie cookie = new Cookie("userName", URLEncoder.encode("您好,哈哈", "UTF-8")); 2 response.addCookie(cookie);
在获取cookie中的中文数据时,再使用URLDecoder类里面的decode(String s, String enc)进行解码,例如:
URLDecoder.decode(cookies[i].getValue(), "UTF-8")
2 Session 对象
Session是服务器端使用的一种记录客户端状态的机制。当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,当客户端后续访问服务器时,只要将标识(ID)号传递给服务器,服务器就能判断出该请求是哪个客户端发送的,从而选择与之响应的Session对象并为其服务。
2.1 Session API
由于Session是与每个请求消息紧密相关的,因此,在HTTPServletRequest中定义了用于获取Session对象的getSession方法,该方法两种重载形式:
public HttpSession getSession(boolean create);
public HttpSession getSession();
//第一个getSession()方法根据传递的参数判断是否创建新的HttpSession对象,如果参数为true,则在相关的HttpSession对象不存在时返回新的HttpSession。否则不创建。
//第二中方法getSession()相当于第一个方法参数为true的情况。
注意:由于getCookie()方法可能会产生发送会话标号的Cookie头字段,因此必须在发送任何响应内容之前调用getSession()方法。
HttpSession接口的常用方法:
方法声明 | 功能描述 |
Sting getId() | 用于返回与当前HttpSession对象关联的会话标识号 |
long getCreationTime() | 返回Session创建的时间。这个时间是创建Session的时间与1970年1月1日0时0分0秒之间时间差的毫秒标识形式 |
long getLastAccessedTime() | 返回客户端最后一次发送与Session相关请求的时间。如上 |
void setMaxInactiveInterval(int interval) | 用于设置当前HttpSession对象可空闲的以秒为单位最长的时间,也就是修改当前会话的默认超时间隔 |
vboolea isNew() | 判断当前HttpSession对象是否是新创建的 |
void invalidate() | 用于强制使Session对象无效 |
ServletContext getServletContext() | 用于返回当前HttpSession对象所书序的Web应用程序对象,即代表当前Web应用程序的ServletContext对象 |
void setArribite(String name, Object value) | 用于将一个对象与一个名称关联后存储到当前的HttpSession对象中 |
String getArribute() | 用于从当前HttpSession对象中返回指定名称的属性对象 |
void removeAttribute(String name) | 用于从当前HttpSession对象中删除指定名称属性 |
2.2 Session保存用户信息过程
由于客户端需要接收、记录和回送Session对象的ID,因此,在通常情况下,Session是借助Cookie技术传递ID属性的。以网站购物为例,以下为Session保存用户信息的原理。
浏览器A和浏览器B都调用buyServlet将商品添加到购物车,然后调用payServlet进行商品结算。A和B购买过程类似。当浏览器A访问购物网站时,服务器为用户甲创建了一个Session对象(相当于购物车)。当浏览器A将vivo添加到购物车时,vivo的信息会存放到Session对象中,同时,服务器会将Session对象的ID属性以Cookie(Set-Cookie:JSESSION=111)的形式返回给浏览器。当浏览器A完成购物并进行结账时,需要想服务器发送结账请求,这时,浏览器将自动在请求消息头中将Cookie(Set-Cookie:JSESSION=111)信息发送给服务器,服务器会根据ID属性找到浏览器A所创建的Session对象,并将Session对象存放的vivo信息取出并进项结算。
2.3 服务器实现一个session为一个用户浏览器服务
服务器创建session出来后,会把session的id号,以cookie的形式回写给客户机,这样,只要客户机的浏览器不关,再去访问服务器时,都会带着session的id号器,服务器发现客户机浏览器带session id过来了,就会使用与之对应的session为值服务。
1 package cn.cookie;
2
3 import java.io.IOException;
4 import javax.servlet.ServletException;
5 import javax.servlet.http.HttpServlet;
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8 import javax.servlet.http.HttpSession;
9
10 public class session1 extends HttpServlet {
11 private static final long serialVersionUID = 1L;
12 public void doGet(HttpServletRequest request, HttpServletResponse response)
13 throws ServletException, IOException {
14 response.setCharacterEncoding("UTF=8");
15 response.setContentType("text/html;charset=UTF-8");
16 //使用request对象的getSession()获取session,如果session不存在则创建一个
17 HttpSession session = request.getSession();
18 session.setAttribute("data", "没有耳朵的猫");
19 String sessionId = session.getId();
20 if(session.isNew()){
21 response.getWriter().print("session创建成功,session的id是:"+sessionId);
22 }else{
23 response.getWriter().print("服务器已经存在该session了,session的id是:"+sessionId);
24 }
25
26 }
27
28 public void doPost(HttpServletRequest request, HttpServletResponse response)
29 throws ServletException, IOException {
30 }
31
32 }
第一次访问时,服务器会创建一个新的sesion,并且把session的Id以cookie的形式发送给客户端浏览器,如下图所示:
点击刷新按钮,再次请求服务器,此时就可以看到浏览器再请求服务器时,会把存储到cookie中的session的Id一起传递到服务器端了,如下图所示:
2018-10-08 11:42:24
以上是关于Cookie 和 Session的主要内容,如果未能解决你的问题,请参考以下文章