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>
    
  • 相关阅读:
    webservice系统学习笔记9-使用契约优先的方式的一个服务端demo(隐式传Header信息)
    webservice系统学习笔记8-简单的权限校验
    JS获取浏览器高宽度,屏幕分辨率和一些定位空隙等
    基于jquery ui修改的不依赖第三方的背景透明的弹出div
    1个比较简单的使用java反射机制获取前台数据进行数据封装的例子
    J2EE项目集成SAP的BO报表
    php-------unset销毁变量并释放内存
    微信小程序------MD5加密(支持中文和不支持中文)和网络请求(get和post)
    谈谈http与https
    php--------合并2个数字键数组的值
  • 原文地址:https://www.cnblogs.com/xiaocongcong888/p/9436274.html
Copyright © 2011-2022 走看看