Cookie

>HTTP协议是一种无状态的协议,WEB服务器本身不能识别出哪些请求是同一个浏览器发出的 ,

  浏览器的每一次请求都是完全孤立的。

>作为 web 服务器,必须能够采用一种机制来唯一地标识一个用户,同时记录该用户的状态问题

>怎么才能实现网上商店中的购物车呢:某个用户从网站的登录页面登入后,再进入购物页面购物时,

 负责处理购物请求的服务器程序必须知道处理上一次请求的程序所得到的用户信息。 

WEB应用中的会话:是指一个客户端浏览器与WEB服务器之间连续发生的一系列请求和响应过程。

WEB应用的会话状态:是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,

WEB服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。

WEB服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,

即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:

属于同一个会话中的请求消息都附带同样的标识号,而属于不同会话的请求消息总是附带不同的标识号,

这个标识号就称之为会话ID(SessionID)。 

在 Servlet 规范中,常用以下两种机制完成会话跟踪
Cookie

Session

Cookie机制 

cookie机制采用的是在客户端保持 HTTP 状态信息的方案

Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件。

一旦WEB浏览器保存了某个Cookie,那么它在以后每次访问该WEB服务器时,都会在HTTP请求头中将这个Cookie回传给WEB服务器。

底层的实现原理: WEB服务器通过在HTTP响应消息中增加Set-Cookie响应头字段,

                              将Cookie信息发送给浏览器,

                              浏览器则通过在HTTP请求消息中增加Cookie请求头字段

                              将Cookie回传给WEB服务器。

一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。

一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。

浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

Cookie的传送过程示意图 

在Servlet程序中使用Cookie

Servlet API中提供了一个javax.servlet.http.Cookie类来封装Cookie信息,它包含有生成Cookie信息和提取Cookie信息的各个属性的方法。

Cookie类的方法:

构造方法: public Cookie(String name,String value)

getName方法

setValue与getValue方法

setMaxAge与getMaxAge方法

setPath与getPath方法

HttpServletResponse接口中定义了一个addCookie方法,它用于在发送给浏览器的HTTP响应消息中增加一个Set-Cookie响应头字段。

HttpServletRequest接口中定义了一个getCookies方法,它用于从HTTP请求消息的Cookie请求头字段中读取所有的Cookie项

Cookie的发送 

1.创建Cookie对象

2.设置最大时效

3.将Cookie放入到HTTP响应报头

如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie;

存储在浏览器的内存中,用户退出浏览器之后被删除。

若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。

将最大时效设为0则是命令浏览器删除该cookie。

发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个 Set-Cookie  HTTP响应报头中。

由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,

因此将这个方法称为是addCookie,而非setCookie。

cookie.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" session="false"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- jsp为服务端的 ,jsp部署在服务器上的,只有访问时候才运行,存放的java代码-->
    <%
        //在JavaWEB    规范中使用 Cookie 类代表 cookie

        //1.获取Cookie
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie ck : cookies) {
                //获取Cookie 和 value
                out.print(ck.getName() + ":" + ck.getValue());
                out.print("<br>");
            }
        } else {
            out.print("没有一个Cookie,正在创建并返回");
            //1.创建一个Cookie对象
            Cookie cookie = new Cookie("name", "lzahxl");

            //setMaxAge 的最大时效,以秒为单位,若为0,表示立即删除该Cokie
            //若为负数,表示不存储该Cookie,若为正数,表示该Cookie 的存储时间
            //2.调用 response 的一个方法吧Cookie 传给客户端
            response.addCookie(cookie);
        }
    %>

</body>
</html>

会话cookie和持久cookie的区别 

如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,

只要关闭浏览器窗口,cookie就消失了。

这种生命期为浏览器会话期的cookie被称为会话cookie。

会话cookie一般不保存在硬盘上而是保存在内存里。

如果设置了过期时间,浏览器就会把cookie保存到硬盘上,

关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。

而对于保存在内存的cookie,不同的浏览器有不同的处理方式。

 

Cookie的读取

1.调用request.getCookies

    要获取浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,

    这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。

2.对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止

 

帮助网站实现提示客户端计算机上次访问网站的时间

实现原理:

将每一个会话作为一次访问过程,将每次会话的开始时间作为每次访问网站的时间,

然后将这个时间以Cookie的形式存储到客户端的计算机中,

客户端进行下次访问时通过该Cookie回传上次访问站点的时间值。

为了让Cookie信息在客户端浏览器或计算机关闭后仍然保持存在,Cookie的保存时间被设置为了一年。

两个练习

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

    <% 
        //若可以获取到请求参数 name, 则打印出欢迎信息。把登录信息存储到 Cookie 中,并设置 Cookie 的最大时效为 30S
        String name = request.getParameter("name");
        if(name != null && !name.trim().equals("")){
            Cookie cookie = new Cookie("name", name);
            cookie.setMaxAge(30);
            response.addCookie(cookie);
        }else{
            //从 Cookie 中读取用户信息,若存在则打印欢迎信息
            Cookie [] cookies = request.getCookies();
            if(cookies != null && cookies.length > 0){
                for(Cookie cookie : cookies){
                    String cookieName = cookie.getName();
                    if("name".equals(cookieName)){
                        String val = cookie.getValue();
                        name = val;
                    }
                }
            }            
        }
        
        if(name != null && !name.trim().equals("")){
            out.print("Hello: " + name);
        }else{
            //若既没有请求参数,也没有 Cookie,则重定向到 login.jsp
            response.sendRedirect("login.jsp");
        }
    %>
</body>
</html>

 book.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>

    <h4>Book Detail Page</h4>

    Book:
    <%=request.getParameter("book")%>

    <br>
    <br>
    <a href="books.jsp">Return</a>

    <%
        String book = request.getParameter("book");

        //.把书的信息以Cookie 方式传回给浏览器,删除一个 Cookie
        // 1.确定要被删除的 Cookie: AFF_BOOK_ 开头的 Cookie 数量大于或者等于5,
        Cookie[] cookies = request.getCookies();

        //用来保存所有以AFF_BOOK_ 开头的Cookie
        List<Cookie> bookCookies = new ArrayList<Cookie>();
        //用来保存books.jsp传入的book 匹配的那个Cookie
        Cookie tempCookie = null;

        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                String cookieName = c.getName();
                if (cookieName.startsWith("AFF_BOOK_")) {
                    bookCookies.add(c);//把满足以 AFF_BOOK_的cookie放入集合中

                    if (c.getValue().equals(book)) {
                        tempCookie = c;
                    }
                }
            }
        }
        //①且若从 books.jsp 页面传入的book 不在 AFF_BOOK_ 的Cookie 中,则删除较早的那个Cookie
        //( AFF_BOOK_   数组的第一个Cookie, 
        if (bookCookies.size() > 5 && tempCookie == null) {
            tempCookie = bookCookies.get(0);
        }

        //②若在其中,则删除该Cookie,再把这个cookie放入最后面
        if (tempCookie != null) {
            tempCookie.setMaxAge(0);
            response.addCookie(tempCookie);
        }

        //2.把从book.jsp 传入的book 作为一个Cookie 返回
        Cookie cookie = new Cookie("AFF_BOOK_" + book, book);
        response.addCookie(cookie);
    %>

</body>
</html>

books.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h4>Books Page</h4>
    
    <a href="book.jsp?book=JavaWeb">Java Web</a><br><br>
    <a href="book.jsp?book=Java">Java</a><br><br>
    <a href="book.jsp?book=Oracle">Oracle</a><br><br>
    <a href="book.jsp?book=Ajax">Ajax</a><br><br>
    <a href="book.jsp?book=JavaScript">JavaScript</a><br><br>
    <a href="book.jsp?book=Android">Android</a><br><br>
    <a href="book.jsp?book=Jbpm">Jbpm</a><br><br>
    <a href="book.jsp?book=Struts">Struts</a><br><br>
    <a href="book.jsp?book=Hibernate">Hibernate</a><br><br>
    <a href="book.jsp?book=Spring">Spring</a><br><br>
    
    <br><br>
    
    <% 
        //显示最近浏览的 5 本书
        //获取所有的 Cookie
        Cookie [] cookies = request.getCookies();
    
        //从中筛选出 Book 的 Cookie:如果 cookieName 为 ATGUIGU_BOOK_ 开头的即符合条件
        //显示 cookieValue
        if(cookies != null && cookies.length > 0){
            for(Cookie c: cookies){
                String cookieName = c.getName();
                if(cookieName.startsWith("AFF_BOOK_")){
                    out.println(c.getValue());
                    out.print("<br>");
                }
            }
        }

    %>
</body>
</html>
All that work will definitely pay off
原文地址:https://www.cnblogs.com/afangfang/p/12741626.html