12、Cookie & Session

作者: sunhaiyu | 来源:发表于2017-03-31 16:23 被阅读128次

    Cookie & Session

    会话的概念

    日常生活来讲,会话就是两个人聊天.。聊天的前提,聊天双方需要有记忆力.。在聊的过程中,都是基于之前聊的状态,继续往下聊。

    我们JavaWeb中,浏览器和服务器也可以看作是双方在聊天(请求,响应).。浏览器服务器双方也需要有"记忆力",保存之前的聊天状态。服务器和浏览器才可以完成会话。

    会话的范围

    两个从打招呼到两人互相道别。是一次会话。

    打开网站,完成我们想做的需求,到关闭浏览器,是一次会话。

    • Cookie: 让浏览器能够记录信息。
    • Session: 让服务器端能够记录信息。

    Cookie原理

    第一次访问服务器时候,服务器响应时候,要求浏览器记住一个信息。response.addCookie(cookie);

    以后每次访问服务器时候,携带第一次记住的信息访问。

    下面是个简单的例子,Aservlet访问服务器,让浏览器记住Cookie,再让Bservlet访问服务器,这时候可以从浏览器将Cookie取出来。

    Aservlet

    package cookie;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Aservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    //      浏览器的Response Headers里面可以看到这么一行。Set-Cookie:username=Tom
    //      所以可以用如下写法
    //      response.addHeader("set-Cookie", "username=Tom");
            // 当然更简单的方式是以下
            Cookie cookie = new Cookie("username", "Tom");
            response.addCookie(cookie);
        }
    }
    

    Bservlet

    package cookie;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Bservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获得浏览器发来的全部cookie
            Cookie[] cookies = request.getCookies();
            Cookie nameCookie = null;
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    if ("username".equals(cookie.getName())) {
                        nameCookie = cookie;
                    }
                }
            }
            if (nameCookie != null) {
                System.out.println(nameCookie.getName() + " : " + nameCookie.getValue());
            } else {
                System.out.println("未找到cookie");
            }
        }
    }
    

    Cookie细节

    Cookie在浏览器存留时间

    默认情况是关闭浏览器就会删除Cookie。如下图过期时间所示。

    在发送cookie之前手动设置:

    cookie.setMaxAge(60*60*24*7*2); //告诉浏览器保存2周
    cookie.setMaxAge(-1); // -1代表 在会话结束时删除cookie(默认情况)
    cookie.setMaxAge(0); // 通常用于删除已经存在的cookie.使用一个寿命为0的cookie,覆盖要删除的cookie
    

    浏览器在什么情况下发送cookie(cookie的路径问题)

    如果 cookie路径是"/cookie_session", 主机(域)是:localhost . 那么浏览器在访问cookie路径的所有子路径时会携带cookie。

    http://localhost:8080/cookie_session/BServlet               会发送
    http://localhost:8080/cookie_session/ABC/BCD/CServlet       会发送
    http://localhost:8080/else/AServlet                     不会发送(项目名)
    http://www.baidu.com/cookie_session/BServlet                不会发送(主机)
    

    Cookie路径的设置

    cookie的默认路径就是 发送cookie的动态资源所在的上一级路径。比如这里/cookie_session/AServlet,是Aservlet发送的,那么默认就是上一级/cookie_session

    手动设置:cookie.setPath("/cookie_session/abc");

    cookie的主机设置

    cookie的主机(域)设置 (了解即可)

    默认情况: 发送Cookie的资源所在主机。
    手动设置:

    //自己当前是什么主机,你就只能设置为什么主机,或者主机名的一部分
    // 假设自己的主机是www.baidu.com那么可以如下设置:
    c.setDomain(".baidu.com");
    

    Cookie的删除

    删除cookie原理就是 使用一个寿命为0的cookie 覆盖需要删除的cookie。c.setMaxAge(0);

    覆盖cookie要求?
    需要路径、键、主机 一致,即可覆盖。

    使用cookie记录中文键值对问题

    为什么不能直接使用中文?

    因为http协议中,除正文部分都不得使用Latin码表以外的其他码表。所以不管是cookie还是之前的Cotent-disposition。都不能直接使用中文。

    1. 使用 URLEncoder 对中文进行url编码。URLEncoder.encode("中文", "UTF-8")
    2. 在获取cookie时,使用URLDecoder进行解码。URLDecoder.decode("中文", "UTF-8")

    使用cookie 记录浏览历史

    先做一个工具类,按填入的参数获取指定Cookie。

    package cookie;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    
    public class CookieUtils {
        public static Cookie getCooieByName(HttpServletRequest req, String key) {
        Cookie cookie = null;
        Cookie[] cookies = req.getCookies();
        
        if (cookies != null) {
            for (Cookie c : cookies) {
                if (key.equals(c.getName())) {
                    cookie = c;
                }
            }
        }
        return cookie;
        }
    }
    
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'list.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <a href="/cookie_session/Cservlet?name=dell">dell</a> <br />
        <a href="/cookie_session/Cservlet?name=lenovo">lenovo</a> <br />
        <a href="/cookie_session/Cservlet?name=hp">hp</a> <br />
        <a href="/cookie_session/Cservlet?name=acer">acer</a> <br />
        <a href="/cookie_session/Cservlet?name=apple">apple</a> <br />
        
        浏览历史:${cookie.history.value }
      </body>
    </html>
    
    package cookie;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Cservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
    //      使用cookie 记录浏览历史.
        
    //      1.获得参数,地址栏的name=lenovo等
            String name = request.getParameter("name");
    //      2.获得Cookie
            Cookie history = CookieUtils.getCooieByName(request, "history");
            //存在 => 修改cookie加上现在浏览器的品牌
            if (history != null) {
              // 重复点击不会继续增加
                if (!history.getValue().contains(name)) {
    
                // 需要注意的是,高版本的Tomcatcookie里不支持“,”逗号。换成其他符号
                    history = new Cookie("history", history.getValue()+"-"+name);
                }
            } else {
            //不存在 => 创建cookie
            history = new Cookie("history", name);
            }
    //      3.将cookie发送会浏览器
            response.addCookie(history);
    //      4.重定向到列表页面
            response.sendRedirect("/cookie_session/history/list.jsp");
            // /cookie_session/WebRoot/history/list.jsp
        }
    }
    

    效果是每点击一次,浏览历史里面就新增一个,重复点击不会继续增加。

    记住用户名和密码

    流程如下。

    登录界面

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'login.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
      <form action="/cookie_session/Dservlet"  >
            用户名:<input type="text" name="name" value="${cookie.remember.value}" />
            <font color="red">${requestScope.error}</font>
            <br>
            密码:<input type="text" name="password" /><br>
            <input type="checkbox" name="remember" value="yes" ${cookie.remember==null?"":"checked=checked"} />记住用户名<br>
            <input type="submit" value="登录" />
        </form>
      </body>
    </html>
    
    

    Dservlet

    package cookie;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Dservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    //      1.获得用户名密码
            String name = request.getParameter("username");
    //      2.校验用户名密码
            if (name == null || "".equals(name.trim())) {
    //          //失败=> 转发到表单页面,并提示错误
                request.setAttribute("error", "请输入用户名!");               request.getRequestDispatcher("/remember/login.jsp").forward(request, response);
                // 转发后不再继续处理逻辑
                return;
            }
            
    //      3.创建cookie 添加要保存的用户名,
            Cookie c = new Cookie("remember", name);
    //      4.查看记住用户名是否被选中
            String remember = request.getParameter("remember");
            //选中 => 设置保存时间为2周
            if ("yes".equals(remember)) {
                c.setMaxAge(60*60*24*7*2);
            } else {
                //没选中=>设置保存事件为0
                c.setMaxAge(0); // 清除cookie
            }
    
    //      5.添加到响应中
            response.addCookie(c);
    //      6.重定向到成功页面
            response.sendRedirect("/cookie_session/index.jsp");
        }
    }
    

    Session原理

    获取session时候,request.getSession();若浏览器第一次访问,服务器会响应一个cookie给浏览器。这个cookie记录的就是sessionId,tomcat生成的sessionid叫做jsessionid。以后每次访问携带着这个sessionId,在服务器里找这个sessionId。找到后就可以获取这个sessionId里面的数据。

    package session;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class Gservlet extends HttpServlet {
        
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            //参数类型是boolean型
            //true=> 无论如何都要获得session
            //false => 如果没有sessionID ,不会获得session
            //request.getSession(true);
            HttpSession session =  request.getSession();//相当于上面的方法 填写true
            // 上面的方法执行后,第一次访问服务器时候,服务器会响应一个cookie给浏览器。这个cookie记录的就是sessionId,tomcat生成的sessionid叫做jsessionid。
            // 比如Set-Cookie:JSESSIONID=44D210CF971936BF86AACD72DED04A82; Path=/cookie_session
            // 再次访问这个网址,携带这个cookie。如Cookie:JSESSIONID=44D210CF971936BF86AACD72DED04A82
            
        }
    }
    

    session的操作

    getAttribute();
    setAttribute();
    removeAttribute();
    getAttributeNames();
    

    session的细节

    session能在服务器端保存多久?

    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>
    

    在tomcat/conf/web.xml 有如上配置。该配置决定了session对象的有效存活时间为30分钟。
    在我们项目的web.xml中, 也可以加上如上配置.区别就是影响的范围不同。在项目中配只影响当前项目.
    3.(了解)。在session对象中,还有如下方法. 该方法也是控制session对象 的有效存活时间的,单位是秒。范围是只影响调用该方法的某个session.
    void setMaxInactiveInterval(int interval)

    session的范围问题

    浏览器第一次访问服务器,服务器创建session对象,会话开始。

    三种方式销毁session

    • 浏览器关闭,保存sessionID的cookie丢失。(Cookie默认在浏览器关闭时候过期) 会话结束。(session还在服务器中,等死)
    • session到了过期时间(默认30分钟无操作)
    • 手动销毁session

    session中的其他方法

    package session;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class Hservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        
            HttpSession session =  request.getSession();
            System.out.println("session.isNew()"+session.isNew());// 判断session是否 是新的.
            System.out.println("session.getCreationTime()"+new Date(session.getCreationTime()));//获得session的创建时间
            System.out.println("session.getId()"+session.getId());//获得session的id
            System.out.println("session.getLastAccessedTime()"+new Date(session.getLastAccessedTime()));//获得最后一次的访问时间
            System.out.println("session.getMaxInactiveInterval()"+session.getMaxInactiveInterval());// 获得session的最大有效时间
            session.setMaxInactiveInterval(60);//设置session的最大有效时间为60秒
            session.invalidate();//需要记住: 立即让session销毁。
         // 所以每次访问都会创建新的session,isNew打印true,ID也是新的,创建时间和上次访问时间也是最新的
    }
    

    验证码例子

    为什么要用session域来存放验证码的正确code?

    • 如果用request域,则开始会向专门生成验证码图片的Aservlet发送请求,正确的code在这个request域中,当我们点击登录,又是一个新的请求,这个新的request里面根本就没有正确code,也不存在和用户自己输入的code进行比较一说。
    • 如果用的application域:Application 的作用范围在服务器一开始执行服务,到服务器关闭为止Application 的范围最、停留的时间也最久。一个web项目只有一个,考虑到线程不安全,所以多个用户共享同一个域,后面的会把前面的覆盖。

    session在会话期间会一直保持着正确的code,所以session域是最合适的。

    登录界面

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'login.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
      <script type="text/javascript">
      function fun1() {
      // 获得img标签对象
      var img = document.getElementById("one");
      // 改变src属性,由于Iservlet没有参数,所以这里随意填,用Date的目的是保证每次访问的唯一性
      img.src = "/cookie_session/Iservlet?date="+new Date();
      }
      </script>
      <form action="/cookie_session/Jservlet"  >
            用户名:<input type="text" name="name" value="${cookie.remember.value}" /> <br>
            密码:<input type="text" name="password" /><br>
            验证码:<input type="text" name="code" size=4 /> ![](/cookie_session/Iservlet)
            <!-- javascript:void(0)什么也不做,让fun1完成 -->
            <a href="javascript:void(0)" onclick="fun1();">看不清,换一张</a>
            <font color="red">${requestScope.error}</font>
            <br />
            <input type="checkbox" name="remember" value="yes" ${cookie.remember==null?"":"checked=checked"} />记住用户名<br>
            <input type="submit" value="登录" />
        </form>
      </body>
    </html>
    
    

    专门用于生成验证码的Iservlet,注意cn.dsna.util.images.ValidateCode用的是第三方包。

    package session;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import cn.dsna.util.images.ValidateCode;
    
    public class Iservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            // 要项浏览器正文输入时,必须指定类型
    //      response.setContentType("image/jpeg");
            
            // 1. 生成验证码
            ValidateCode code = new ValidateCode(120, 40, 4, 2);
            // 2. 将正确答案放进Session
            String correctCode = code.getCode();
            request.getSession().setAttribute("code", correctCode);
            // 3. 将图片发送给浏览器
            System.out.println(correctCode);
            code.write(response.getOutputStream());
        }
    
    }
    
    

    点击登录跳转到Jservlet,取出用户输入的code和session域存放的正确code比较。

    package session;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Jservlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            // 1. 获得用户填写的验证码
            String userCode = request.getParameter("code");
            // 2.  获得session中的正确验证码
            String correctCode = (String) request.getSession().getAttribute("code");
            // 3. 比较两者
            if (userCode != null && userCode.equalsIgnoreCase(correctCode)) {
                // 验证成功,重定向到登录成功的页面
                response.sendRedirect("/cookie_session/index.jsp");
            } else {
                request.setAttribute("error", "请输入正确的验证码!");
                request.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        }
    }
    

    如上图,验证码填错了会转发到登录界面。

    注意是转发过去是一次请求,转发过去还是刚才的jsp页面。${requestScope.error}才能收到request.setAttribute("error", "请输入正确的验证码!");的错误信息;如果是重定向又重新请求了,重新加载jsp,不会显示错误信息。

    购物车例子

    商城商品页面。list.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
        <h1>商品列表</h1>
        <table border="1" >
            <tr>
                <td>
                    肥皂<br>
                    <a href="/cookie_session/Kservlet?name=0"  >点击加入购物车</a>
                </td>
                <td>
                    蜡烛<br>
                    <a href="/cookie_session/Kservlet?name=1" >点击加入购物车</a>
                </td>
            </tr>
            <tr>
                <td>
                    被罩<br>
                    <a href="/cookie_session/Kservlet?name=2" >点击加入购物车</a>
                </td>
                <td>
                    枕头<br>
                    <a href="/cookie_session/Kservlet?name=3" >点击加入购物车</a>
                </td>
            </tr>
        </table>
            <a href="/cookie_session/cart.jsp" >查看购物车</a>
      </body>
    </html>
    
    

    购物车详情,cart.jsp

    <%@page import="java.util.Map.Entry"%>
    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'cart.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <h1>购物车</h1>
        <table border="1">
            <tr>
                <th>商品名称</th>
                <th>商品数量</th>
            </tr>
            <%
                Map<String,Integer> cart = (Map<String,Integer>)session.getAttribute("cart");
                if(cart!=null && cart.size()>0){
                    for(Entry<String,Integer> en : cart.entrySet()){
                    %>
                    <tr>
                        <td><%=en.getKey() %></td>
                        <td><%=en.getValue() %></td>
                    </tr>
                    <% }
                }
             %>
        </table>
      </body>
    </html>
    
    

    Kservlet

    package session;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Kservlet extends HttpServlet {
    
       public void doGet(HttpServletRequest request, HttpServletResponse response)
               throws ServletException, IOException {
    
           //0 准备数组,与页面商品对应
           String[] products = {"肥皂","蜡烛","被罩","枕头"};
                   
    //      1. 获得当前请求要添加的商品
           String indexStr = request.getParameter("name");// 0 ~ 3 
                   
           String productName = products[Integer.parseInt(indexStr)];
    //      2.从Session中取出存放购物车的map
           Map<String,Integer> cart = (Map<String, Integer>) request.getSession().getAttribute("cart");
           if(cart==null){
    //      //取不到=>初始化map,LinkedHashMap保证存入和取出的顺序相同,因为HashMap是无序的
           cart = new LinkedHashMap<String, Integer>();
           //并放入session
           request.getSession().setAttribute("cart", cart);
           }
    //      3.使用当前要添加的商品从map中取值,默认数量为1
           Integer count = cart.put(productName, 1);
           // 不为空说明值被覆盖,加一。为空说明上面设置为1是正确的
           if(count!=null){
               cart.put(productName, count+1);
           }
           //取不到=> 放入map,设置数量为1
       //取得到=> 将数量+1放回去
    //      4.重定向回商品列表页面
           response.sendRedirect("/cookie_session/list.jsp");
       }
    }
    
    

    注意:后退或者刷新,再次选择物品、购物车依然会累计。但是当浏览器关闭后,再次访问购物车就清零了。因为cookie被销毁,sessionId已经没有了,再去服务器找的时候是没有携带的,需要新建。

    Cookie和Session的区别

    • session 在服务器端,cookie 在客户端(浏览器)
    • session 默认被存在在服务器的一个文件里(不是内存)
    • session 的运行依赖 sessionId,而 sessionId 是存在 cookie 中的,也就是说,如果浏览器禁用了 cookie ,同时 session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 sessionId)
    • session 可以放在 文件、数据库、或内存中都可以。
    • 用户验证这种场合一般会用 session

    因此,维持一个会话的核心就是客户端的唯一标识,即 sessionId


    by @sunhaiyu

    2017.3.31

    相关文章

      网友评论

        本文标题:12、Cookie & Session

        本文链接:https://www.haomeiwen.com/subject/svevottx.html