【Servlet篇4】cookie和session

news2024/11/16 21:00:52

在这一篇文章当中,我们提到了什么是cookiesession

【网络原理8】HTTP请求篇_革凡成圣211的博客-CSDN博客HTTP的常见属性,URL,User-Agent,Refer,get 和post的区别https://blog.csdn.net/weixin_56738054/article/details/129180661?spm=1001.2014.3001.5502它们分别是客户端会话技术和服务端会话技术。

分别把用户的信息保存在客户端磁盘服务端,二者一般是相互配合使用的。


       当用户访问一个网站之后,这个网站会把用户的关键信息(例如身份标识符)存储到cookie当中,也就是用户的本地磁盘当中。

       当后续用户再次访问这个网站的时候,就会携带这个cookie,然后在服务器当中根据这个cookie来获取这个用户的其他信息。

下面,就来聊一下session和cookie的常见api

目录

HttpSession session=req.getSession();

 当传入参数为true的时候:

当传入参数为false的时候:

当调用getSession()方法的时候,会做什么事情

步骤1:创建会话

步骤2:获取会话

HttpSession对象

setAttribute()和getAttribute()

Cookie[] getCookies方法

resp.addCookie()方法

实现登录-跳转页面的案例

第一步:约定登录前后端交互的格式

登录接口的请求方式:

登录接口的响应方式:

第二步:约定如何获取主页的交互

获取主页的请求方式:

响应的格式:

第三步:编写登录的接口,并且把用户登录的信息保存在session当中

第四步:编写访问index页面的servlet

实现一个用户访问页面的次数的功能

 如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?

总结:cookie和session的区别
​​​​​​​​​​​​​​


HttpSession session=req.getSession();

这一个方法,既可以用于获取到服务器上面的会话,又可以用于创建会话。

但是,这一个方法在HttpServletRequest当中是存在多态的。

 当传入参数为true的时候:

会话存在,则获取;会话不存在,则创建


当传入参数为false的时候:

会话存在,则获取;会话不存在,则返回null


当调用getSession()方法的时候,会做什么事情

步骤1:创建会话

首先先获取到HTTP请求头当中cookie这个属性里面的sessionId字段

接着,判断这一个sessionId是否在当前的服务器当中存在。

如果不存在,那么就进入创建会话的逻辑。

       第一步:首先创建一个HttpSession对象,并且生成一个sessionId(用16进制来表示);

       第二步:把sessionId作为key,这一个session对象作为value。保存到服务器的一个类似于"哈希表"的结构当中。(这个数据是保存到内存当中的,并不是持久化的)

       第三步:服务器返回一个HTTP响应,把sessionId通过Set-cookie字段返回给浏览器。

也就是返回给用户

       然后用户下次再次访问的时候,就可以通过这个cookie字段来获取了。 

下面,图解一下创建会话的流程:


步骤2:获取会话

先获取到请求的cookie里面的sessionId字段。

然后判断这个sessionId是否在当前的服务器上面存在(也就是是否在这个哈希表当中存在)

如果有,那么直接返回这个sessionId对应的对象。


HttpSession对象

每一个HttpSession对象都是通过键值对的形式来存储数据的。

当存储数据的时候,需要调用session.setAttribute(k,v)的方式来存储。

key是String的类型,value是Object的类型

看上去有点绕,怎么出现了套娃呢...那就画个图来解释一下吧~:

 一个服务器当中可以有多个session对象,每一个session对象都拥有一个sessionId

一个session对象都对应多个键值对


setAttribute()和getAttribute()

这两个方法,左边的那个是拥有设置key-value的。右边那个是通过key来获取value的。

当调用setAttribute之后,就相当于往已经创建的session对象当中存放key和value


Cookie[] getCookies方法

        通过调用req.getCookies方法,可以获取到用户提交的HTTP请求头当中的cookie字段对应哪些键值对:代码实现

@WebServlet("/servlet4")
public class Servlet4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       Cookie[] cookies= req.getCookies();

       for(int i=0;i<cookies.length;i++){
           Cookie cookie=cookies[i];
           System.out.println(cookie.getName()+"...."+cookie.getValue());
       }
    }
}

 运行结果:

 使用Fidller抓包:

可以看到,此时服务器就获取到了两个cookie对象。


resp.addCookie()方法

       此处传入的是一个Cookie类型的数据,Cookie也是由键值对组成的结构。键和值都是String类型的数据。

Cookie cookie=new Cookie("hello","hi");
Cookie cookie1=new Cookie("hello","hi");
resp.addCookie(cookie);
resp.addCookie(cookie1);

       这个addCookie方法,其实就相当于给客户端浏览器发送一个cookie类型的键值对。

       然后,可以在HTTP响应报头的set-cookie字段当中看到这一个字段。

   


下面,通过一个网页登录的案例来体会一下cookie和session。

实现登录-跳转页面的案例

第一步:约定登录前后端交互的格式

登录接口的请求方式:

协议版本:HTTP/1.1

请求方法:POST;

请求路径:/Servlet;

接收方式(Content-type)application/x-www.form-urlencoded

(也就是userName="***"&password="***")这样的格式


登录接口的响应方式:

响应行:HTTP/1.1 302(需要重定向);

重定向:Location: index。(重定向到index这个路径)


第二步:约定如何获取主页的交互

获取主页的请求方式:

HTTP版本:HTTP/1.1

请求方法:GET;

请求路径:/index;

没有参数需要提交


响应的格式:

HTTP版本:1.1;

状态码:200;

响应格式:Content-Type: text/html(返回一个html页面)


第三步:编写登录的接口,并且把用户登录的信息保存在session当中

 登录的时候,通过req.getSession()来创建一个session对象

并且把userName存放到session域当中。 

约定需要跳转的路径(/index)

     @WebServlet("/login")
public class Servlet5 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        //处理用户请求
        String userName=req.getParameter("userName");
        String password=req.getParameter("password");
        //此处简单模拟一下登录成功的情况
        if("张三".equals(userName)&& "123".equals(password)){
            //往会话当中存储键值对:用于保存用户登录的信息
            //此处指定的参数为true,那么:需要此时会创建一个sesion对象
            HttpSession session=req.getSession(true);
            //把用户名存入session当中,代表用户已经登录成功了
            session.setAttribute("userName",userName);
            resp.sendRedirect("index");
        }else{
            //登录失败
            resp.getWriter().write("login faild");
        }
    }
}

第四步:编写访问index页面的servlet

       再次调用req.getSession方法,但是此处需要指定参数为false

       因为此处的session就是为了验证用户登录与否,无需再次创建新的会话。

       此处的session对象和第三步当中的session期待是同一个session对象。

       因为期待是同一个会话。

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到用户名
        //此处getSession参数为false,原因:此处已经创建过会话了
        HttpSession session =req.getSession(false);
        resp.setCharacterEncoding("utf-8");
        //根据key来获取value
        String userName= (String) session.getAttribute("userName");
        //返回一个主页
        resp.getWriter().write("<h3>欢迎你!"+userName);
    }
}


实现一个用户访问页面的次数的功能

无需太大的改动。只需在用户登录的时候,设置一个count统计用户登录的次数。这一个count需要使用session保存。

然后在页面(index)处,每一次用户取出来数据,都要+1。

代码实现:

登录页面

@WebServlet("/login")
public class Servlet5 extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         req.setCharacterEncoding("utf-8");
        //处理用户请求
        String userName=req.getParameter("userName");
        String password=req.getParameter("password");

        //此处简单模拟一下登录成功的情况
         System.out.println(userName+"..."+password);
        if("张三".equals(userName)&& "123".equals(password)){
            //往会话当中存储键值对:用于保存用户登录的信息
            //此处指定的参数为true,那么:需要此时会创建一个sesion对象
            HttpSession session=req.getSession(true);
            //把用户名存入session当中,代表用户已经登录成功了
            session.setAttribute("userName",userName);
            //登录成功,默认初始的值为0
            session.setAttribute("count",0);
            resp.sendRedirect("index");
        }else{
            //登录失败
            resp.getWriter().write("login faild");
        }
    }
}

index页面

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到用户名
        //此处getSession参数为false,原因:此处已经创建过会话了
        HttpSession session =req.getSession(false);
        //根据key来获取value
        String userName= (String) session.getAttribute("userName");
        resp.setCharacterEncoding("utf-8");
        //获取一个count的值
        Integer count= (Integer) session.getAttribute("count");
        Integer newCount=count+1;
        //在session当中保存自增过后的count
        session.setAttribute("count",newCount);
        //返回一个主页
        resp.getWriter().write("<h3>欢迎你!"+userName+"您访问此页面的次数为:"+newCount);
    }
}

 如果在其中一个浏览器登录了,可以在另外一个浏览器直接访问登录页面吗?

 不行的。来做个实验看一下:

 首先,启动Tomcat,默认在360安全浏览器打开页面。

然后登录(登录的接口跟上面的是一样的,都是/login),同时使用Fidler抓包

然后,再抓一下访问index页面的URL的包:


换一个浏览器,再次访问index页面的URL

       可以看到,换了一个浏览器,因为cookie当中包含的sessionID不一样了,也就没有办法保存原来sessionid当中的值,那么就无法获取到在原来的浏览器保存的session信息了。

        (每一个浏览器都会有自己的cookie,也就意味着不同的浏览器有不同的sessionId)


总结:cookie和session的区别

使用对象数据类型安全性存储大小存储位置
cookie

针对网站:

每一个网站都会被分配一组cookie

(String,String)比较低,容易丢失、篡改较小;一个cookie不超过3K保存在客户端浏览器(磁盘)
session

针对用户:

只有客户端才可以访问。

程序为客户端添加一个sessionId.

一个sessionId对应一个HttpSession对象

(String,Object)比较高可以存储任意大的数据保存在服务端

       

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/389572.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[数据集][VOC][目标检测]河道垃圾水面漂浮物数据集目标检测可用yolo训练-1304张介绍

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1304 标注数量(xml文件个数)&#xff1a;1304 标注类别数&#xff1a;1 标注类别名称:["trash"] …

如何从错误中成长?

在上一篇文章“技术人的犯错成本”里&#xff0c;我和你聊了技术人可能会犯的各式各样的错误&#xff0c;也举了很多例子&#xff0c;说明了技术人犯错的成本。在竞争激烈的互联网时代&#xff0c;试错当然是好事&#xff0c;但了解错误成本&#xff0c;避免不应该犯的错误&…

测试概念及模型

今日目标掌握测试用例包含的基本内容使用等价类方法设计出测试用例1. 软件测试分类&#xff08;复习&#xff09;1.1 按阶段划分单元测试测试&#xff1a;针对单个功能进行测试&#xff0c;如&#xff1a;登录、购物车等开发&#xff08;更多的理解&#xff09;&#xff1a;针对…

C/C++实现发送邮件功能(附源码)

C++常用功能源码系列 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务于工作实践。 专栏介绍:专栏讲本人近10年后端开发常用的案例,以高质量的代码提取出来,并对其进行了介绍。…

Linux -- 作业控制进程

作业控制 &#xff1a;官方 &#xff1a; 作业控制是一个命令行功能&#xff0c;允许一个shell 实例来运行和管理多个命令。作用 &#xff1a; 使用作业控制&#xff0c;可以选择性暂停&#xff0c;恢复&#xff0c;以及异步运行命令&#xff0c;让 shell 可以在子进程运行期…

【1599. 经营摩天轮的最大利润】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮转座舱&#xff0c;但每次轮转都需要支付一定的运行成本 runningCost 。摩…

基于flask+bootstrap+echarts+mysql的鱼村小馆订餐后台管理系统

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

[1.3.3]计算机系统概述——系统调用

文章目录第一章 计算机系统概述系统调用&#xff08;一&#xff09;什么是系统调用&#xff0c;有何作用&#xff08;二&#xff09;系统调用与库函数的区别&#xff08;三&#xff09;小例子&#xff1a;为什么系统调用是必须的&#xff08;四&#xff09;什么功能要用到系统调…

English Learning - L2-4 英音地道语音语调 双元音 [eɪ] [aɪ] [aʊ] [əʊ] [ɔɪ] 2023.03.2 周四

English Learning - L2-4 英音地道语音语调 双元音 [eɪ] [aɪ] [aʊ] [əʊ] [ɔɪ] 2023.03.2 周四节奏发音对比双元音概述双元音 [eɪ]发音技巧对应单词的发音对应句子的发音双元音 [aɪ]发音技巧对应单词的发音对应句子的发音双元音 [aʊ]发音技巧对应单词的发音对应句子的…

Android kotlin 系列讲解(进阶篇)高级项目架构模式 - MVVM

<<返回总目录 1、MVVM是什么 MVVM是Model-View-ViewModel的缩写&#xff0c;是一种高级项目架构模式。 MVVM架构可以将程序结构主要分成三个部分&#xff1a; Model&#xff1a;数据模型部分&#xff0c;包括从服务端获取的json数据或者从本地获取的数据等等View&…

【GlobalMapper精品教程】056:图像融合(高光谱+全色)操作案例教程

本文讲解GlobalMapperV24.0汉化版图像增强:融合(高光谱+全色)操作案例教程 文章目录 一、图像融合概述二、图像融合案例1. 加载数据2. 图像融合3. 图像导出一、图像融合概述 图像融合是指将不同类型传感器的影像进行融合,既能使图向具有较高的空间分辨率,又具有多光谱的特…

工具篇(五)炫酷排版,尽在LaTeX:让你的文档飞升吧!

作者的话 作为一个文本排版工具&#xff0c;latex一直以来都备受科研工作者、学生和出版社的青睐。但是对于初学者来说&#xff0c;latex的学习曲线可能会有些陡峭。因此&#xff0c;我写这篇博客旨在为初学者提供一个简单易懂的latex教程&#xff0c;让大家能够快速入门并掌握…

C++—输入输出流

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1. 输入输出流2. 文件的输入输出2.1 写文件2.2 读文件前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 我的电脑为什么从 C 盘开始&#…

Compose 动画 (三) : AnimatedVisibility 从入门到深入

1. AnimatedVisibility 是什么 AnimatedVisibility可以实现Compose组件的显示和隐藏&#xff0c;并且可以指定显示/隐藏时候的动画效果。(EnterTransition/ExitTransition) 和 animateXxxAsState、animateContentSize、Crossfade、AnimatedContent 这几个API一起&#xff0c;都…

一文详解像素、DPI、分辨率之间的关系

像素像素&#xff1a;是指在由一个数字序列表示的图像中的一个最小单位&#xff0c;称为像素。像素可以用一个数表示&#xff0c;比如一个“0.3兆像素”数码相机&#xff0c;它有额定30万像素&#xff1b;也可以用一对数字表示&#xff0c;例如“640x480显示器”&#xff0c;它…

单目标追踪——【相关滤波】C-COT原理与ECO基于C-COT的改进

目录C-COT&#xff1a;Continuous Convolution Operator Tracker文章侧重点连续卷积算子目标追踪框架初始化过滤器&#xff1a;追踪流程ECO文章侧重点因式卷积因子生成采样空间模型模型更新策略论文链接&#xff1a;C-COT&#xff1a;Beyond Correlation Filters: Learning Con…

【MySQL】表连接

一、为什么要学习 因为不合理的使用连接会导致慢查询 二、什么是连接 参与连接的表叫做 连接表&#xff0c; 连接就是把 各个连接表 进行的组合 &#xff08;笛卡儿积&#xff09;加入结果集并返回 三、连接查询 如何只是对表进行大量的连接&#xff0c;笛卡儿积作用得到的…

ChatGPT会取代程序员么?今天让ChatGPT写了个程序,感觉离失业不远了

文章目录ChatGPT会取代程序员么&#xff1f;今天让ChatGPT写了个程序&#xff0c;感觉离失业不远了问题&#xff1a;保存和ChatGPT的聊天记录对话实录以及吐槽1. 把当前页面转成markdown格式的方法2. 用油猴子可以实现么&#xff1f;3. 编写一段油猴子代码&#xff0c;实现刚才…

Redis十大类型——Set与Zset常见操作

Redis十大类型——Set与Zset常见操作Set命令操作简列基本操作展示删除移动剪切集合运算Zset基本操作简列添加展示反转按分数取值获取分数值删除分数操作下标操作如果我们对Java有所了解&#xff0c;相信大家很容易就明白Set&#xff0c;在Redis中也一样&#xff0c;Set的value值…

4、树(中篇)

前言:前节二叉树只能适用于静态查找,不能实现动态插入、删除等。如何解决以下两个问题: 静态查找与动态查找针对动态查找,数据如何组织?4.1 二叉搜索树 4.1.1 什么是二叉搜索树 二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树。 二叉搜索树:一棵…