JavaWeb笔记整理+图解——Web开发会话技术:Cookie 与 Session

本篇将会讲解Cookie 与 Session

阅读本篇需要的前置知识有:Java基础、HTML、http协议、Servlet等

如果你缺乏这些前置知识阅读本篇可能会遭遇困难,建议你先阅读我整理的以下笔记后再来阅读本篇^_^:

JavaSE笔记_i_Water_boy的博客-优快云博客

JavaWeb笔记整理——HTML、CSS、JavaScript_html css java-优快云博客

JavaWeb开发笔记图解整理(二)——XML、Tomcat、Servlet-优快云博客

Javaweb笔记整理+图解——HTTP协议-优快云博客

一、会话

浏览器打开到浏览器关闭

什么是会话

我们打开浏览器进行一系列的操作,一直到浏览器关闭这一整个过程,用户和浏览器服务器之间的交互,就是一次会话。

在一次会话过程中会产生很多数据,如服务器发送给浏览器的Cookie,和服务器保存在本地的Session

二、Cookie

在登录一些网站的时候,我们常常会看到这些网站要求我们接收Cookie,那什么是Cookie呢?

1、什么是Cookie?

Cookie是一种由服务器发送并存储在用户浏览器中的小型文本文件,用于保存用户的会话信息和其他少量数据。它们可以帮助网站记住用户的偏好、登录状态以及其他个性化设置,从而提供更好的用户体验。

Cookie的应用场景

设想这样一个场景:我们登录了一个视频网站,当我们切换视频时,浏览器会自动帮我们存储观看过的视频到历史记录中。

通常,我们可以通过Servlet将这些数据存储到数据库中。然而,对于一些小型应用来说,每次访问历史记录都需要连接数据库,这会影响应用的性能。为了解决这个问题,我们可以使用Cookie。

使用Cookie存储历史记录

我们可以将访问的历史记录制作成一个Cookie,存储在浏览器中。这样,每次访问时,浏览器只需读取本地的Cookie即可显示观看过的视频,而不需要每次都访问数据库。这不仅减少了服务器的负担,也提高了应用的响应速度。

跨浏览器的数据同步

如果我们希望在不同的浏览器中也能看到观看过的视频,可以在用户首次登录时从数据库读取历史记录,然后将这些数据制作成Cookie存储在浏览器中。以后用户在同一浏览器中访问时,就不需要再访问服务器了,从而提高了运行速度。

Cookie是浏览器存储的一段小数据(Cookie 直译为 曲奇 可见其数据量并不大)。

它有着自己的生命周期,浏览器会根据Cookie设定的生命周期自动的将其销毁。

浏览器持有Cookie时,在访问服务器的资源时,Cookie会封装在Request对象中,然后服务器会根据Request对象中的Cookie对返回给浏览器的资源进行相应的变化和改动。这也就达到了每个用户所看到的内容不一样的实现。

2、Cookie 的基本使用

Cookie的结构

Cookie的数据结构比较像一个HashMap,它也是由一对键值对构成的,分别是name - value 两个数据都是String类型的。

创建一个Cookie对象

在Servlet中,我们可以创建一个Cookie对象:

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie = new Cookie("username", "aaa");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

添加Cookie对象

创建一个Cookie对象后,不意味着Cookie对象就会被发送会浏览器并保存,我们还需要进行添加操作。

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie = new Cookie("username", "aaa");

        // 添加一个Cookie对象 把cookie对象添加到 response响应中
        response.addCookie(cookie);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

添加了Cookie后,Cookie就会被服务器返回给浏览器,然后浏览器就会将Cookie对象保存起来,从而下一次返回给服务器。

读取Cookie

当浏览器给服务器一个request请求后,如果有Cookie对象,服务器自然会读取Cookie,并进行相应的处理。

我们在Servlet中自然可以进行读取Cookie的操作:

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie = new Cookie("username", "aaa");

        // 添加一个Cookie对象 把cookie对象添加到 response响应中
        response.addCookie(cookie);

        // 读取Cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie1 : cookies) {
            System.out.println(cookie1.getName() + "-" 
                    + cookie1.getValue());//username-aaa
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

先获取一个Cookie数组,然后就可以读取每个Cookie的name和value。

Cookie的生命周期

Cookie有的时候我们不希望浏览器一直保存,所以Cookie 会有一个生命周期。

Cookie的默认生命周期是会话级别的,也就是当一个浏览器关闭时,Cookie就会被自动销毁。

如果我们不想Cookie在浏览器关闭时就被销毁,可以自行设置生命周期。

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie = new Cookie("username", "aaa");
        
        // 设置Cookie生命周期
        // 这里填写一个int值,以秒为单位
        cookie.setMaxAge(3600); //一小时

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

手动删除一个Cookie

手动删除一个Cookie其实就是把一个Cookie的生命周期设置为0,并添加进去。

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie = new Cookie("username", "aaa");
        
        //设置生命周期为0
        cookie.setMaxAge(0);
        // 添加后,cookie对象将从浏览器中直接被删
        response.addCookie(cookie);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

Cookie的有效路径

我们可以设置Cookie的有效路径,从而让不同的资源可以获取到不同的Cookie,而不是一股脑的获取全部的Cookie。

public class CookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 创建一个Cookie对象
        Cookie cookie1 = new Cookie("username1", "aaa");
        Cookie cookie2 = new Cookie("username2", "bbb");

        //当访问 /cookie/aaa资源 时才会发送这个cookie1对象
        cookie1.setPath("/cookie/aaa");
        //当访问 /cookie 路径下的资源时 会发送这个cookie2对象
        cookie1.setPath("/cookie");
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

3、Cookie的注意细节

一个Cookie只能表示一个信息,即一个 name - value对。

一个web站点可以给一个浏览器发送多个Cookie,而一个浏览器也可以存放多个web站点的多个Cookie。

删除Cookie时,必须要保持路径一致,不然不会删除。

在删除cookie时,如果这个cookie已经设置了路径,那么删除时要确保cookie添加生命周期为0时,添加的路径保持和之前一致。

三、Session 

1、什么是Session?

有时候我们登录一些网站时,会自动的登录。这是因为我们之前登录过这个网站,所以网站记住了我们曾经登录过这个信息。

这样我们就可以无需重新登录就使用网站上的内容。

这样的功能我们显然使用Cookie就可以实现,但是由于Cookie是保存在浏览器中的,我们甚至可以直接看到Cookie的信息。所以如果我们使用Cookie来实现上面的功能就有很大的安全性问题

所以我们引出了Session,把浏览器发送的数据保存在服务端,只要用户登录过,在接下来一段时间内,服务器检测到有登录的Session对象,用户就无需登录,实现自动登录的功能。 

而Session是每个用户的浏览器独享的,服务器不会将一个用户A的Session数据发送给用户B。

2、Session的基本使用

Session的结构

Session也是一个类似HashMap的结构,前面一个String 对应一个 Object对象 存储在服务器中。

Session使用方法

public class SessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // session 对象的获取
        HttpSession session = request.getSession();

        // Session 属性的获取
        Object username = session.getAttribute("username");

        // Session 属性修改
        session.setAttribute("username", "abc");

        // Session 删除
        session.removeAttribute("username");

        // 判断是不是新创建出来的 Session对象
        boolean aNew = session.isNew();
        System.out.println(aNew);

        // 获取Session所对应的id
        // 这个id对应着浏览器存储着的一个Cookie
        String id = session.getId();
        System.out.println(id);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

3、Session的底层实现机制(重、难点)

这里是一个Session底层的简单示意图。

我们要着重的关注getSession()这个方法。 这个方法使我们之后学习的重点。

 浏览器A访问Session数据时,首先会看服务器中是否有一个自己对应的Session对象,如果没有就会在Tomcat服务器中通过getSession()创建一个Session对象(是的,getSession方法会创建Session对象),放入相应的数据,如果有就直接进行相应的操作。

而这个getSession()方法中发生了很多事情,我们下面画个图继续讲解:

第一次访问

首先,我们第一次打开一个浏览器,此时浏览器中是没有任何Cookie的,我们给浏览器发送一个请求,服务器帮浏览器创建一个Session,这时候就会调用getSession方法。

然后getSession方法会判断浏览器的请求中是否带有Cookie = JSessionId ,如果没有,getSession方法就会咋服务器的内存中创建一个Session对象并给这个Session对象创建一个SessionId,并赋给这个Session对象:

 

然后服务器在返回http响应时,会根据Session对象是否被创建而返回Cookie,如果创建了一个Session对象,那么就会给浏览器返回一个Cookie: name = JSessionId -  value = 1736481 (我随便取的) 。

 然后浏览器中的Cookie 就不再是空了,而是存储了一个JSessionId。

第二次访问

第二次浏览器访问服务器,调用服务器的getSession()方法,依然会判断是否有JSessionId存在,这里第二次访问时显然是存在的。

 发现存在JSessionId后,会进行下一次判断,看看服务器内存中是否有与这个Id相对应的Session对象。因为Session可能已经被销毁,服务器此时可能会没有对应的Session对象,所以这里需要进行这个判断。

 这里的服务器内存中存在这个对象,所以服务器会直接进行相关的操作,而不会再创建一个新的Session。

第三次访问,第一次的Session对象已被服务器销毁

第三次 访问时,由于Session生命周期已经到了,Session被服务器销毁,进行判断浏览器是否有SessionId时,浏览器确实有,但是这个SessionId却没有与之对应的Session对象,所以此时依然会创建一个Session并分配一个新的SessionId。

 此时由于新创建了一个Session对象,所以此时服务器会给浏览器发送一个新的Cookie,从而让浏览器保存新的JSessionId

 这里需要补充一点:

服务器设置Cookie时,新的Cookie如果是同名name的,那么就会覆盖掉原来的Cookie。

而Session也是一样,会覆盖掉同名的值。

所以这里浏览器的JSessionId就会被覆盖为新的Id

4、Session的生命周期

Session的生命周期和Cookie有较大不同。

设置生命周期

我们可以在Servlet中设置生命周期:

public void setMaxInactiveInterval(int interval) 设置 Session 的超时时间(以秒为单位), 超过指定的时长,Session 就会被销毁。如果设置为负值则永远不会被销毁。

这里的超时时间,指的是Session的访问最大时间间隔,如果超过这个时间间隔还没有访问,那么这个Session对象就会被销毁。

举个例子,我这里设置Session的生命周期为30min,我第一次访问这个Session的时间是5:00,
然后第二次访问的时间是5:29 ,那么这个Session就还没有超时,因为两次访问的时间间隔是29min,没有超过我们设置的最大时间间隔,所以Session不会被销毁。

但如果我们第一次访问的时间是5:00 ,而第二次访问的时间是5:31,那么就超过了两次访问的最大时间间隔,这里就不会访问到这个Session因为已经被销毁了。

需要注意的是,第一次访问这个Session的时间是5:00,然后第二次访问的时间是5:29,那么5:31时,Session不会被销毁,而是在5:59时被销毁,因为最新一次访问的时间的5:29,所以最大的访问时间间隔会在5:59时达到,所以在5:31时Session并不会被销毁。

public void invalidate() 让当前 Session 会话立即无效

如果没有调用 setMaxInactiveInterval() 来指定 Session 的生命时长,Tomcat 会以 Session 默认时长为准,Session 默认的超时为 30 分钟可以在 tomcat 的 web.xml 设置默认超时时间


下一篇我来继续讲解JSP,求点赞收藏关注~^_^

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值