草庐IT

day21-web开发会话技术03

liyuelian 2023-04-16 原文

WEB开发会话技术03

10.问题引出

  • 问题引出

    1. 不同的用户登录网站后,不管该用户浏览网站的哪个页面,都可以显示登录人的名字,还可以随时去查看自己购物车中的商品,这是如何实现的呢?
    2. 也就是说,一个用户在浏览一个网站的不同页面时,服务器是如何知道是张三在浏览这个页面,还是李四在浏览这个页面?
  • 解决方法1- 使用cookie

    在用户登录的时候,服务器可以将用户信息通过cookie的形式保留在浏览器。每当用户访问不同的网页(发送HTTP请求),浏览器都会将该cookie发送给服务器,服务器通过获取cookie的值,在网页上就可以显示当前用户的信息;同时服务器也可以通过cookie(用户信息)找到用户操作用户在数据库中对应的数据。

    但是使用cookie会存在以下问题:第一是cookie不能存放大的数据;第二是cookie不安全,不能存放敏感信息;第三,cookie不是跟一个用户关联的。如果一个cookie是长期保存的,那么当其他人打开浏览器时,也可以登录你的账号,因此单单使用cookie来实现也不太理想。

  • 解决方法2- 使用session

    session是服务器端的技术,也就是说session的数据是保存在服务器端的。服务器在运行时会为每一个用户的浏览器创建一个其独享的session对象(该对象可以理解为一个集合)。

    由于session为每个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的session中读取/添加数据,从而完成任务。

11.Session基本介绍

  1. 当用户打开浏览器,访问某个网站,操作session时,服务器就会在内存(在服务端)为该浏览器分配一个session对象,该session对象被这个浏览器独占,如上图

  2. 这个session对象也可以看做是一个容器/集合,session对象默认存在的时间为30min(在tomcat/conf/web.xml中可以修改)

11.1session可以做什么

  1. 网上商城的购物车
  2. 保存登录用户的信息
  3. 将数据放入到Session中,供用户在访问不同页面时,实现跨页面访问数据
  4. 防止用户非法登录到某个页面
  5. .......

11.2如何理解session

  1. session存储结构示意图

  2. 你可以把session看做是一容器(类似HashMap),有两列(k-v),每一行就是session的一个属性

  3. 每个属性包含有两个部分,一个是该属性的名字(String),一个是该属性的值(Object)

12.Session常用方法

  1. 创建和获取session(api一样)

    HttpSession session = request.getSession();
    

    第一次调用是创建Session会话,之后调用是获取创建好的Session对象

  2. 向session添加属性

    session.setAttribute(String name,Object val);
    
  3. 从session得到某个属性

    Object obj = session.getAttribute(String name);
    
  4. 从session删除某个属性

    session.removeAttribute(String name);
    
  5. isNew(); 判断是不是刚创建出来的Session

  6. 每个Session都有一个唯一标识的Id值(即JSESSIONID),通过getId()得到Session的会话Id值

13.Session底层实现机制

13.1原理分析图

整个过程如下:

一个浏览器向服务器发送请求,要操作session时,一定会调用request.getSession()方法。

  • 这个方法会先判断浏览器是否携带了JSESSIONID的cookie:
    • 如果没有携带,就会在服务器内存中创建一个session对象,并且为这个session分配一个sessionId。如上图,可以理解为服务器内存有一个map<String,Object>,sessionId作为map的key,session对象作为key关联的value。如此,这个sessionId就和该session对象关联起来了。
    • 如果携带了,就会进一步判断:判断服务端的map中是否已经存在了该JSESSIONID对应的session对象
      • 如果map中没有,就会创建一个session对象,并且为这个session分配一个新的sessionId。
      • 如果map中已经存在了该JSESSIONID对应的session对象,就直接操作。

如果服务器在本次会话中,创建了session,则在响应头中将以Set-Cookie:JSESSIONID=xxxx的形式返回一个cookie给浏览器保存。下一次浏览器发送请求时,服务器就可以拿到cookie中的JSESSIONID的值,在map中找到该浏览器对应的session,直接操作。

这里的map可以理解为在Tomcat中还维护了一个容器HashMap<String,HttpSession>,这个容器中以JSESSIONID为key,以session为value,完成两者的绑定。

13.2代码演示

演示Session底层实现机制-创建和读取Session

13.2.1创建session的实例分析

web.xml:

<servlet>
    <servlet-name>CreateSession</servlet-name>
    <servlet-class>com.li.session.CreateSession</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>CreateSession</servlet-name>
    <url-pattern>/createSession</url-pattern>
</servlet-mapping>

CreateSession:

package com.li.session;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

public class CreateSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println("CreateSession doPost被调用...");
        //1.获取session(同时也可能创建session)
        HttpSession session = request.getSession();//注意这个地方已经把sessionId分配了
        //2.给session获取id
        System.out.println("当前sessionid= " + session.getId());
        //3.给session存放一些数据
        session.setAttribute("email", "zs@qq.com");
        //4.给浏览器发送一个回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("<h1>创建/操作session成功...</h1>");
        writer.flush();
        writer.close();
    }
}
  1. 首先访问http://localhost:8080/cs/createSession:

  2. 抓包显示:

    走的是如下流程:

  3. 服务器后端显示:

  4. 此时浏览器存储的JSESSIONID变成了新的值:

  5. 此时,如果再次访问服务器,就会携带cookie中新的jsessionid给服务器,服务器不再返回jsessionid。

    ​ 走的是如下流程:

  6. 如果redeployTomcat,关闭浏览器并重新打开,直接访问http://localhost:8080/cs/createSession,这时候的请求头将不会携带jsessionid(因为关闭浏览器时默认删除了cookie),服务器返回的响应头将会携带一个jsessionid(因为重新发布tomcat,会清空服务器内存,这时请求的资源createSession程序会创建一个session,因此服务器会返回一个与之关联的jsessionid)

    这时候走的就是如下流程:

13.2.2读取session的实例分析

web.xml:

<servlet>
    <servlet-name>ReadSession</servlet-name>
    <servlet-class>com.li.session.ReadSession</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ReadSession</servlet-name>
    <url-pattern>/readSession</url-pattern>
</servlet-mapping>

ReadSession:

package com.li.session;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

public class ReadSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println("ReadSession doPost被调用...");
        //演示读取session
        //1.获取session,如果没有session也会创建
        HttpSession session = request.getSession();
        //2.给session获取id
        System.out.println("ReadSession 当前sessionid= " + session.getId());
        //3.读取属性
        Object email = session.getAttribute("email");
        if (email != null) {
            System.out.println("session属性 email= " + (String) email);
        } else {
            System.out.println("session中没有 email属性");
        }
        //3.给浏览器发送一个回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("<h1>读取session成功...</h1>");
        writer.flush();
        writer.close();
    }
}
  1. redeployTomcat,首先在浏览器中访问http://localhost:8080/cs/createSession(目的是创建一个和浏览器关联的session,因为redeployTomcat会删除服务器的session)

  2. 然后访问http://localhost:8080/cs/readSession,并抓包:

  3. 在服务器后台输出如下:第一行输出是我们创建session时获取的sessionid,第二行是我们读取session时获取的sessionid,并获取其属性。

有关day21-web开发会话技术03的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  3. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  5. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  6. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  9. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  10. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

随机推荐