zoukankan      html  css  js  c++  java
  • springbootDay03 cookie和session 购物车技术

    一、会话技术

    1. 什么是会话

    在计算机术语中,会话指的是客户端和服务器交互通讯的过程。简单的理解,大家可以看成是两个普通的人在打电话。一次电话从通话开始到挂断,可以看成是会话。

    • 会话的特征
      • 会话能够把同一用户发出的不同请求之间关联起来。不同用户的会话应当是相互独立的
      • 会话一旦建立就一直存在,直到用户空闲时间超过了某一个时间界限,会话才会中断。 好比大家打电话,超过了某一定时间就会自动断开。

    2. 什么是会话技术

    HTTP是一种无状态协议,每当用户发出请求时,服务器就会做出响应,客户端与服务器之间的联系是离散的、非连续的。当用户在同一网站的多个页面之间转换时,根本无法确定是否是同一个客户。

    举例如下:

    1. 我们在电商网站上选购商品,即便没有登录,假如购物车。下一次我们再打开网站,还是能够看到上一次添加到购物车的商品
    2. 我们在一些网站登录了之后,过了几天我们在打开这个网站,还能认识我们,还能在右上角显示 欢迎您 xxx
    3. 当我们再次登录一些论坛时,总会显示上一次我们访问论坛的时间。

    3. 会话技术的分类

    会话技术主要常用的有两种, 一种是Cookie , 另一种是 Session .

    1. 什么是cookie

    Cookie 可以翻译为“小甜品,小饼干” ,  Cookie 实际上是指小量信息,是由 Web 服务器创建的,将信息存储在用户计算机上的文件。当用户通过浏览器访问服务器的时候,浏览器会自动携带早前存储的cookie ,传递给服务器。
    

    2. Cookie的应用场景

    所有服务器想要让客户端帮忙存储一些数据,以便下次访问能够识别客户的情形,都可以使用cookie,如:

    1. 商品浏览记录

    2. 购物车信息

    3. 记住账号密码

      ...

    3. Cookie的基本使用

    大家要记住一个核心,cookie是服务器生成,然后寄存在客户端的一小份数据。 那么服务器如何把这一小份数据给客户端呢? 只能依靠前面讲过的response对象了。

    Cookie cookie = new Cookie("key" ,"value");
    response.addCookie(cookie);
    

    4. Cookie的分类

    cookie有分临时性(也称之为会话级别cookie),也有持久性。

    • 临时性Cookie

    默认情况下,关闭浏览器后,cookie就销毁掉了。

    • 持久性Cookie

    可以设置保存时长

    5. 获取上次访问时间

    img01

    • 页面准备
     <form action="user_login" method="post">
            用户名:<input type="text" name="username"/></br>
            密  码:<input type="password" name="password"/></br>
            <input type="submit" value="登录"/>
        </form>
    
    • controller
    @RestController
    public class UserController {
        private static final String TAG = "UserController";
    
        @RequestMapping("user_login")
        public String login(HttpServletRequest request , HttpServletResponse response ,  String username , String password){
    
            System.out.println(username + " : " + password);
            HttpSession session = request.getSession();
          //  session.setAttribute("name","zhangsan");
    
            String id = session.getId();
            System.out.println("id=" + id);
    
            //1. 判断账号密码
            if("admin".equals(username) &&  "123".equals(password)){
    
                String result = "欢迎您 , "+ username;
    
                //2.要获取cookies
                Cookie[] cookies = request.getCookies();
    
                //有cookie
                if(cookies != null){
    
                    //就想看cookie里面有没有带上次的时间
                    for(Cookie cookie : cookies){
                        //如果能成立,就表示找到了上一次访问的时间。
                        if("last".equals(cookie.getName())){
    
                            long time = Long.parseLong(cookie.getValue());
    
                            Date date = new Date();
                            date.setTime(time);
    
                            result += "
     上一次访问时间是:"+date.toLocaleString();
                        }
                    }
                }
                //只要有登录成功,就必须返回最新的登录时间。
                String time = System.currentTimeMillis()+"";
                Cookie cookie = new Cookie("last" , time);
                cookie.setMaxAge(60*60*24*7);
                response.addCookie(cookie);
    
                return result;
            }
            
            return "登录失败";
        }
    }
    

    6. Cookie的问题

    1. cookie 大小有限制,每个服务器在最多不能超过20个。
    2. cookie 是存放在客户端上,信息不安全,有被截获的可能

    三、 Session

    1. 什么是session

    Session是基于Cookie的一种会话机制。 Session服务器上的一段内存空间 , 可以用来存储数据。

    Cookie是服务器返回一小份数据给客户端,并且存放在客户端上。 Session是,数据存放在服务器端。

    cookie

    数据存放在客户端
    
    数据不安全
    
    减轻服务器压力, 用户磁盘占用比较多。 
    
    存放的数据有限
    

    session

    数据存放在服务器端
    
    数据相对比较安全。
    
    服务器压力大一点。
    
    存放的数据 依赖服务器的内存空间。 
    

    3. Session的简单使用

    1. 获取session

      HttpSession session = request.getSession()

    2. 存值

      session.setAttribute(name ,value);

    3. 取值:

      session.getAttribute(name);

    4. 移除值

      session.removeAttribute(name);

    5. 让session失效 作废

      session.invalidate();

    6. 获取id值

      session的id值就是这一块内存空间的唯一标识符。 session.getId() .

    4. Session的背后细节

    • 第一次访问

    那么session都没有创建,并且咱们的请求对象里面也不带任何的cookie过来。 那么这个时候会在内存中给你创建一个新的session区域,并且把这个session的id值放到cookie里面给我们的浏览器返回。 注意这些事情都是服务器端自己做的。所以cookie是一个临时性的cookie。 关闭浏览器就销毁cookie了

    • 第二次访问

    如果是第二次访问,那么浏览器会把之前的那个cookie给带过来, 服务器收到了cookie,里面有我们上一次给的sessionid 值, 那么这个时候再调用request.getSesion() , 它先会拿我们待过来的id ,到内存里面去找有没有session的 id值跟这个cookie带过来的一样 ,如果有,就直接返回这个内存空间, 否则就创建新的session空间

    img03

    5. session 销毁的细节!

    img04

    1. 关闭浏览器并不能让session销毁。 因为session是服务器的一块内存空间, 它的销毁不依赖客户端的浏览器关闭还是不关闭。
    2. 再次访问的时候,我们的浏览器已经没有了那个sessionid值,所以就找不到了以前的那一块空间。所以打开浏览器重新访问,会拿到的是全新的session空间。 但是原来的那个session还存在,只不过我们无法操作它而已。
    3. 如果真的项操作以前的session,我们要手动往cookie里面存session id 值,并且设置成持久性cookie

    注意: cookie的那个name不能乱写。 JSESSIONID

    • 销毁session
    1. invaidate()
    2. 自动失效。 有效期。 默认30分钟

    6. Session的作用范围 & 生命周期

    • 作用范围

      sesison 作用范围: 一次会话范围内有效。

    • 生命周期

      何时创建

      第一次调用request.getSession()就创建。 
      

      何时销毁

      关闭服务器 
      
      session超时了。默认30分钟。 从最后一次请求开始计时。
      
      调用invalidate . 让空间失效、作废
      

    7. 购物车案例

    日常生活中,大家都是有过购物的经验,喜欢什么商品,先把它添加到购物车中,后续再付款。 那么购物车是如何实现的呢? 其实购物车可以使用cookie来实现,也可以使用session来实现。真正的企业的购物车要实现起来还得配合缓存数据库来实现。咱们接下来使用session来实现一个简易的购物车即可

    img02

    • 准备工作

    需要在项目的build.gradle 中添加 thymeleaf依赖

    compile("org.thymeleaf:thymeleaf-spring4:2.1.4.RELEASE")
    
    • 在模板页面上,要记得引入命名空间
     <html xmlns:th="http://www.thymeleaf.org" >
    

    1. 显示商品列表

    • index.html
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h2><a href="list">开始购物</a></h2>
    </body>
    </html>
    
    • 商品实体类
    public class Product {
       
    
        private int id; // 商品的编号
        private String name; //商品名字
        private double price ; //商品价格
        
        get & set 方法
        ...
    }
    
    • 商品controller
    @Controller
    public class ProductController {
        private static final String TAG = "ProductController";
    
        //准备商品数据
        private static List<Product> list;
        static{
            list = new ArrayList<Product>();
    
            list.add(new Product(1,"iphone6s" ,3788));
            list.add(new Product(2,"小米8" ,2788));
            list.add(new Product(3,"vivo20" ,4788));
            list.add(new Product(4,"meizu6" ,3690));
            list.add(new Product(5,"诺基亚200" ,188));
        }
    
    
        @RequestMapping("list")
        public ModelAndView list(){
    
            //1. 构建商品集合
            
            //2. 存储数据到model
            ModelAndView modelAndView  =new ModelAndView();
    
            //设置模型数据
            modelAndView.addObject("list" , list);
    
            //设置跳转的目标是哪里。 list.html
            modelAndView.setViewName("list");
    
            return modelAndView;
        }
    }
    
    • 商品列表 list.html 位于 /resources/templates/下
    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" >
    <head>
        <meta charset="UTF-8"/>
        <title>商品列表页面</title>
    </head>
    <body>
    
        <h2>商品列表</h2><br/>
    
        <table>
    
            <thead>
                <td width="100px">编号</td>
                <td width="100px">名称</td>
                <td width="100px">价格</td>
                <td width="100px">操作</td>
            </thead>
    
            <!--从这里开始就是真正的商品数据显示了
                p 遍历 list集合的出来的每一个元素对象, 其实好就是商品对象。
                aa: 表示遍历的状态信息
                    ${aa.index} :遍历的索引
            -->
            <tr th:each="p,status:${list}">
                <td th:text="${p.id}">100</td>
                <td th:text="${p.name}">苹果笔记本</td>
                <td th:text="${p.price}">9999</td>
                <!--<td ><a href="addToCart?index=1">加入购物车</a></td>-->
                <td ><a th:href="@{addToCart(index=${status.index})}">加入购物车</a></td>
            </tr>
        </table>
    
    
    </body>
    </html>
    

    2. 加入购物车

    点击加入购物车需要跳转到controller , 根据提供的索引下标,获取到对应的商品,添加到购物车 Map

    • 添加购物车方法
     //添加商品到购物车, 现在拿到的是商品的索引
        @RequestMapping("addToCart")
        public String addToCart(HttpServletRequest request , int index){
    
            System.out.println("要添加商品到购物车了~");
    
            HttpSession session = request.getSession();
    
            //1. 根据索引,获取到要添加到购物车的商品
            Product product  = list.get(index);
    
            //2. 加入购物车 购物车其实就是商品和数量的对应关系。
            Map<Product , Integer> map = (Map<Product , Integer>)session.getAttribute("cartMap");
            //第一次来,连购物车都没有
            if(map == null){
                map = new HashMap<Product , Integer>();
            }
    
            //判断购物车里面是否有该商品 ,如果有  数量 + 1  ,如果没有,数量-1
            if(map.containsKey(product)){
                map.put(product , map.get(product) +1 );
            }else{
                map.put(product , 1 );
            }
    
            //3. 存储到session中。
            request.getSession().setAttribute("cartMap" , map);
    
            //当前的跳转是基于template/list.html ,所以需要重定向跳转到中转页面
            return "redirect:transfer.html";
        }
    
    • 中转页面

    该页面只是一个简单的静态页面,所以位于 resource/static下

    <body>
    
        <a href="list"><h2>继续购物</h2></a><br>
        <a href="toCart"><h2>去购物车查看</h2></a><br>
    
    </body>
    

    3. 显示购物车

    通过点击去购物车查看, 即可跳转到购物车页面,显示商品。

    • cart.html

    该页面是用于显示动态数据,所以需要放到模板 templates下。

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" >
    <head>
        <meta charset="UTF-8"/>
        <title>Title</title>
    </head>
    <body>
    
        <h2>购物车列表</h2>
    
        <table>
           <thead>
                <td  width="100px">商品名称</td>
                <td  width="100px">商品价格</td>
                <td  width="100px">购买数量</td>
                <td  width="100px">小计</td>
           </thead>
    
            <!--把session里面的购物车拿出来遍历显示。 购物车是一个map集合
                map集合的遍历出来,其实就是一个key 和 一个value 的组合 。
                这种组合entry
                m就是entry
                map<Product , Integer>
            -->
            <tbody>
                <tr th:each="m:${session.cartMap}">
                    <td th:text="${m.key.name}">联想鼠标垫</td>
                    <td th:text="${m.key.price}">10.0</td>
                    <td th:text="${m.value}">1</td>
                    <td th:text="${m.key.price * m.value}">1</td>
                </tr>
    
            </tbody>
    
    
        </table>
    
    </body>
    </html>
    
  • 相关阅读:
    Oracle 安装报错 [INS-06101] IP address of localhost could not be determined 解决方法输入日志标题
    Linux下安装oracle数据库提示DISPLAY not set. Please set the DISPLAY and try again。
    redhat 关机注销命令详解
    VirtualBox的四种网络连接方式
    修改RedHat的系统显示时间
    insufficient memory to configure kdump(没有足够的内存)解决方法(待验证、待解决)
    xen坑随笔 heartbeat dpkg垃圾数据库清除
    tomcat 监控脚本
    负载均衡随笔
    GIT命令介绍
  • 原文地址:https://www.cnblogs.com/xiaocongcong888/p/9436274.html
Copyright © 2011-2022 走看看