当前位置: 首页 > news >正文

【Servlet篇4】cookie和session

在这一篇文章当中,我们提到了什么是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 {@Overrideprotected 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 {@Overrideprotected 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 {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取到用户名//此处getSession参数为false,原因:此处已经创建过会话了HttpSession session =req.getSession(false);resp.setCharacterEncoding("utf-8");//根据key来获取valueString userName= (String) session.getAttribute("userName");//返回一个主页resp.getWriter().write("<h3>欢迎你!"+userName);}
}


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

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

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

代码实现:

登录页面

@WebServlet("/login")
public class Servlet5 extends HttpServlet {@Overrideprotected 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);//登录成功,默认初始的值为0session.setAttribute("count",0);resp.sendRedirect("index");}else{//登录失败resp.getWriter().write("login faild");}}
}

index页面

@WebServlet("/index")
public class IndexServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取到用户名//此处getSession参数为false,原因:此处已经创建过会话了HttpSession session =req.getSession(false);//根据key来获取valueString userName= (String) session.getAttribute("userName");resp.setCharacterEncoding("utf-8");//获取一个count的值Integer count= (Integer) session.getAttribute("count");Integer newCount=count+1;//在session当中保存自增过后的countsession.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)比较高可以存储任意大的数据保存在服务端

       

相关文章:

【Servlet篇4】cookie和session

在这一篇文章当中&#xff0c;我们提到了什么是cookie和session。 【网络原理8】HTTP请求篇_革凡成圣211的博客-CSDN博客HTTP的常见属性&#xff0c;URL&#xff0c;User-Agent&#xff0c;Refer,get 和post的区别https://blog.csdn.net/weixin_56738054/article/details/1291…...

考研流程,可以进来转一转(考研你不知道的事情)(详细版)

之前有听过好多人说要考研&#xff0c;那么&#xff0c;考研的信息&#xff0c;如何获取呢&#xff0c;考研都有哪些流程呢。 初试开始到考试&#xff1a;↓ 1、了解考研信息。 2、确定自己要报考的专业。&#xff08;本专业or跨考&#xff09; 3、选择地区 4、选择要报考的学…...

3.2 LED闪烁流水灯蜂鸣器

LED闪烁1.1 电路连接示意图LED采用低电平点亮的方式&#xff0c;利用ST-Link的3.3V进行供电。1.2程序设计1.21知识储备GPIO配置步骤步骤&#xff1a;1. 第⼀步&#xff0c;使⽤RCC开启GPIO的时钟2. 第⼆步&#xff0c;使⽤GPIO_Init()函数初始化GPIO3. 第三步&#xff0c;使⽤输…...

刷题笔记3 | 203. 移除链表元素、707设计链表,206.反转链表

目录 203. 移除链表元素 707、设计链表 206.反转链表 203. 移除链表元素 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;h…...

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战

[一篇读懂]C语言十一讲&#xff1a;单链表的删除和单链表真题实战1. 与408关联解析及本节内容介绍1 本节内容介绍2. 单链表的删除操作实战3. 单链表真题解读与解题设计1 题目解读2 解题设计第一阶段&#xff1a;双指针找中间结点第二阶段&#xff1a;原地逆置第三阶段&#xff…...

【C++初阶】list的使用

大家好我是沐曦希&#x1f495; 文章目录一、前言二、构造三、迭代器四、增删查改1.头插头删2.尾插尾删3.查找和插入4.删除五、其他成员函数1.排序和去重2.splice和remove3.resize一、前言 list本质是带头双向循环链表&#xff0c;本文只对list的一些常用接口进行说明&#xf…...

HTML 布局

网页布局对改善网站的外观非常重要。 请慎重设计您的网页布局。 在线实例 使用 <div> 元素的网页布局 如何使用 <div> 元素添加布局。 使用 <table> 元素的网页布局 如何使用 <table> 元素添加布局。 网站布局 大多数网站会把内容安排到多个列中&a…...

如何在虚拟机中安装ikuai软路由系统

首先访问ikuai官网下载固件固件下载-爱快 iKuai-商业场景网络解决方案提供商 (ikuai8.com) 根据需求下载 然后创建一个虚拟机&#xff0c;点击下一步 选择更下载的ISO映像文件&#xff0c;点击下一步 点击下一步 设置一下名称和储存位置&#xff0c;点击下一步 根据需求设置&a…...

Java 多线程 --- 线程协作 wait/notify

Java 多线程 --- 线程协作 wait/notifywait / notifyObject.wait() , Object.notify() / notifyAll()notify 和 wait 的原理notify会导致死锁的问题wait / notify的开销以及问题wait / notify 在多线程中, 如果程序拿到锁之后, 但是没有满足指定条件而不能继续往下执行, 我们可…...

【PyTorch】教程:torch.nn.Hardsigmoid

torch.nn.Hardsigmoid 原型 CLASS torch.nn.Hardsigmoid(inplaceFalse) 参数 inplace (bool) – 默认为 False 定义 Hardsigmoid(x){0if x≤−3,1if x≥3,x/61/2otherwise\text{Hardsigmoid}(x) \begin{cases} 0 & \text{if~} x \le -3, \\ 1 & \text{if~} x \ge 3…...

【手把手一起学习】(八) Altium Designer 20修改和自定义原理图标题栏

1 修改原理图标题栏 直接对原理图标题栏属性进行修改&#xff0c;操作如图所示&#xff1a; 修改后&#xff0c;并不会显示&#xff0c;故该方法不可用&#xff1a; 正确的操作如下&#xff0c;先选择合适的模板&#xff1a; 然后&#xff0c;进行属性的修改&#xff1a; 此时…...

业务流程测试

用例设计主要问题主要问题存在于&#xff1a;1、测试点分析&#xff1a;逻辑性不强对于整个页面功能划分不清晰&#xff1b;不同测试点归类不清晰&#xff1b;不能形成相对固定的套路&#xff0c;书写耗费大量时间...2、测试用例&#xff1a;关于&#xff0c;要细致到什么程度&…...

[极客大挑战 2019]EasySQL 1

[极客大挑战 2019]EasySQL 1解题POC一、解题思路之暴力破解1. 弱口令2. 暴力破解二、解题思路之万能密码1. 什么是万能密码2. 测试过程解题POC 直接点击登录获取flagflag{62f0d2ca-579e-450e-941f-5f7c23a8baf7} 一、解题思路之暴力破解 这题是万能密码&#xff0c;所以暴力破解…...

vulnhub raven2复现

1.扫描全网段&#xff0c;找出了存活主机ip为192.168.85.144 nmap 192.168.85.0/24 2.nmap扫描端口 nmap -p1-65535 192.168.85.144 3.访问此网站&#xff0c;没找到什么地方可以利用漏洞 &#xff0c;查看中间件为wordpress 4.使用dirb对该网站进行目录扫描 dirb http://1…...

LeetCode 剑指 Offer II 079. 所有子集

给定一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3…...

打印名片-课后程序(Python程序开发案例教程-黑马程序员编著-第二章-课后作业)

实例3&#xff1a;文本进度条 进度条以动态方式实时显示计算机处理任务时的进度&#xff0c;它一般由已完成任务量与剩余未完成任务量的大小组成。本实例要求编写程序&#xff0c;实现图1所示的进度条动态显示的效果。 下载中下载完成图1文本进度条 实例分析 在本实例中可以将…...

为什么我们在判断字符串不为null后还要判断字符串长度大于0?

我们在做字符串判断时一般会&#xff1a; if (s ! null && s.length() > 0) {} 但是我就在想&#xff0c;字符串不为空了&#xff0c;那么他一定有值&#xff0c;字符串长度不就大于0吗&#xff0c;所以s.length()>0是不是有点多余&#xff1f; 我的思维误区是…...

javaEE 初阶 — 应用层中的 DNS 协议(域名解析系统)

文章目录什么是域名1. 如何建立 域名 与 IP 的对应关系2. 域名的分级什么是域名 域名也就是平常所说的网址&#xff0c;比如 www.baidu.com。 其实网络上的服务器要访问这个网址&#xff0c;需要的是 IP 地址。、 但是 IP 地址比较拗口不方便记忆&#xff0c;于是就有使用一些…...

【网络】-- 网络编程套接字(铺垫、预备)

目录 理解源IP地址和目的IP地址 认识端口号 端口号 理解源端口号和目的端口号 套接字 认识TCP与UDP协议 网络字节序 socket编程接口 socket 常见API sockaddr结构 理解源IP地址和目的IP地址 就如同我们唐僧的取经路&#xff1a; 唐僧的出发地到目的地&#xff1a;东…...

一文打通@SentinelResource

Sentinel 提供了 SentinelResource 注解用于定义资源&#xff0c;并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等 如果使用的是Sentinel Annotation AspectJ Extension&#xff0c;需要导这个依赖 <dependency><groupId>com.alibaba.csp</…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...