SpringSession笔记

news2024/9/22 21:22:44

第一章、Session会话管理概述

Session和Cookie回顾

Session机制

由于HTTP是无状态的协议,每次浏览器与服务器的交互过程就是一次对话,对话结束之后服务器不能记住你这个人。下次对话的时候服务端无法识别你是上次的人,所以需要一种机制来记录用户的状态信息,这个机制就是session。

Cookie机制

每次HTTP请求的时候,客户端都会发送相应的cookie信息到服务端。

第一次创建Session时,服务端会在HTTP协议中向客户端 Cookie 中记录一个Session ID,以后每次请求把这个会话ID发送到服务器,这样服务端就知道客户端是谁了。

url重写机制

如果客户端的浏览器禁用了Cookie,那么就需要在请求的url地址后面添加上session的id,这样来识别。

浏览器和服务器对Session和Cookie机制的使用

发起请求

浏览器:每次发起请求都会将Cookie数据传递给后端的tomcat服务器。这个Cookie中存放的就是一个类似于map集合的,sessionid的值。

tomcat:tomcat启动之后会启动一个jvm虚拟机,里面存放着Session的id和对应的内存地址。

如果用户不是第一次请求,将浏览器传递过来的cookie中的sessionid取出来找到对应的内存地址并找到session对象。这样就可以追踪用户的状态信息。

如果用户是第一次请求,那么浏览器传递过来的cookie中什么都没有,这样tomcat就会创建一个session和对应的id,分别存放在jvm和返回到浏览器。

Session会话管理带来的问题以及解决方案

session会话的问题

在web的实际开发过程中,session是交给tomcat容器管理的,里面记录着用户的状态以及相关的数据。

在单击版本中,这种管理方式并没有问题。但是如果使用集群部署,将项目部署在多台tomcat中,使用负载均衡的方式访问。那么session存放在tomcat中就会出现无法共享的问题。

session会话共享方案
  1. 使用容器的拓展插件来实现:

基于tomcat的tomcat-redis-session-manager插件;

基于jetty的jetty-session-redis插件、memcached-sessuib-manager插件

这个方案的好处对项目来说是透明的,但是依赖容器,容器升级会导致重新配置

底层原理是:复制session到其他服务器,有一定的延时,并且不能部署太多

  1. 使用nginx负载均衡的ip_hash策略实现用户每次访问都绑定到同一台服务器

局限性就是ip不能改变,但是在网络中的ip一般是DHCP的动态形式。改变地理位置也容易导致ip发生改变。

并且如果某一台服务器发生故障就会导致ip重新分配,导致访问不到原来的服务器。

  1. 使用框架会话管理工具,也就是spring session。这个方案既不依赖于tomcat服务器,又不需要改动代码,由spring session框架为我们提供。

第二章、Spring Session入门

SpringSession简介

Spring Session 是Spring家族中的一个子项目,它提供一组API和实现,用于管理用户的session信息

它把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题,Session信息存储在Redis中,可简单快速且无缝的集成到我们的应用中;

spring session特性
  1. 提供用户session管理的API和实现

  1. 提供httpSession,以中立的形式取代web容器中的session

  1. 支持集群的session处理,不必绑定到具体的web容器去解决集群session共享问题

SpringSession的使用(简单例子)

第一步、创建一个简单的session会话例子

使用servlet创建一个get和set方法,set在session域中填入一个数据,并打印填入成功,然后get中取出并打印数据。

需要的依赖:

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <!-- servlet依赖的jar包start -->

        <!-- jsp依赖jar包start -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
        </dependency>

第二步、测试两个服务器的session是否共享

将这个项目部署到两个不同的tomcat服务器,注意服务器和jvm的端口号。第一个叫9100,第二个叫9200.

启动两个服务器,然后再9100访问set方法创建session对象,然后再9200访问get方法看看能否取到数据。

经过测试发现9200无法取到9100中存放的session信息。这时候就是两个服务器各自持有自己的session不共享导致正常的服务无法运行。

第三步、添加SpringSession集成配置

添加依赖
<!-- Spring session redis 依赖start -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.3.1.RELEASE</version>
        </dependency>
        <!-- Spring session redis 依赖end -->
        <!-- spring web模块依赖 start -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.16.RELEASE</version>
        </dependency>
        <!-- spring web模块依赖end -->
在web.xml文件中配置springSessionRepositoryFilter过滤器和加载Spring配置文件
<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
创建applicationContext-session.xml
A、    配置一个RedisHttpSessionConfiguration类
<context:annotation-config/>:用于激活已经在Spring容器中注册的bean或者注解,因为我们通过容器创建的bean中,底层有可能使用了其它的注解,我们通过<context:component-scan>就不能指定具体的包了,所以可以使用<context:annotation-config/>激活
<!-- spring注解、bean的处理器 -->

<context:annotation-config/>

<!-- Spring session 的配置类 -->
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>

B、    配置Spring-data-redis
<!-- 配置jedis连接工厂,用于连接redis -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="${redis.hostName}"/>
    <property name="port" value="${redis.port}"/>
    <property name="password" value="${redis.password}"/>
    <property name="usePool" value="${redis.usePool}"/>
    <property name="timeout" value="${redis.timeout}"/>
</bean>

<!--读取redis.properties属性配置文件-->
<context:property-placeholder location="classpath:redis.properties"/>

c、配置redis.properties文件

redis.hostName=192.168.235.128
redis.port=6379
redis.password=123456
redis.usePool=true
redis.timeout=15000
在applicationContext.xml中导入applicationContext-session.xml

将集成spring session的xml单独写成一个然后引入spring需要的配置文件。这样整个程序的耦合性会比较低。

第四部、部署测试

重复之前的两台服务器存放和读取操作,开启linux服务器上开启的redis数据库。

  • 在浏览器中访问tomcat9100服务器的setSession

  • 在浏览器中访问tomcat9200服务器的getSession

部署成功。

第三章、SpringSession常见的应用场景

同域名下相同项目集群实现Session共享

准备三台tomcat,然后将一个项目p2p(服务提供者)复制成两份存放到两台tomcat部署。需要这两台服务器实现session共享。另一台服务器部署dataservice(消费者)。

实现部署

  1. 在linux上开启三台tomcat服务器,然后使用xftp将p2p项目和dataservice项目上传到tomcat下的webapps目录下。

  1. 在linux里面启动mysql数据库,使用客户端工具创建需要的数据库。

  1. 修改一下dataservice中的数据源和dubbo注册地址,修改一下p2p项目的信息。

  1. 启动zookeeper服务注册中心。

  1. 启动redis服务器。

  1. 启动nginx实现服务的反向代理并负载均衡。

upstream www.p2p.com{
            server 127.0.0.1:9100;
            server 127.0.0.1:9200;       
} 

直接测试项目发现负载均衡后登陆不成功,这是因为session负载均衡后session丢失了。

解决方式nginx反向代理负载均衡时session共享

第一种、使用ip_hash的轮询策略

一个服务器负责一个用户,但是弊端很大

第二种、使用springSession

将最先前项目中的springSession中配置的一个单独的xml文件拷贝到tomcat9100和tomcat9200的p2p项目WEB-INF/classes下,那个配置文件中封装了所有的springsession配置需要的信息。包括spring session的配置类,spring-data-redis的连接信息等。

这样就实现了集群部署中的session共享了。

同域名下不同项目的session共享

在同一个域名下,有多个不同的项目(项目的上下文根不一样)比如:

这样的话两个同域名下的不同项目会创建两个不同的session。这两个请求cookie的路径不一致,即使存在Spring session共享机制,但是后台服务器会认为这是两个不同的会话,所以不能实现共享。

解决方式

设置Cookie路径为根路径,域名路径

<!-- Spring session 的配置类 -->
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    <!--设置cookie的存放方式-->
    <property name="cookieSerializer" ref="defaultCookieSerializer"/>
</bean>
<!--设置cookie的存放方式具体实现-->
<bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
    <property name="cookiePath" value="/"/>
</bean>

同根域名不同二级子域名下的项目实现Session共享

修改本地host文件C:\Windows\System32\drivers\etc

使用windows的host映射代理的域名转换实现对网址的访问。

将nginx的ip转换为多个不同地址的域名存放到host文件中

测试

这时候使用本地的idea启动两台tomcat服务器

然后使用浏览器访问

在9200中存放session域的数据

在9100中取出session域中的数据

发现失败

分析Session共享失败的原因

虽然这个两个cookie的路径都设置为了/,但是这两个cookie的域名不一致,虽然加上了Spring Session共享机制,但是服务器认为这是两个不同的会话,所以不能实现共享。

解决方式,设置cookie的域名为根域名 web.com

在applicationContext-session.xml文件中,加如下配置:

注意:域名要和hosts文件中配置的域名后面一样

<!--设置cookie的存放方式具体实现-->
<bean id="defaultCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
    <property name="cookiePath" value="/"/>
    <property name="domainName" value="web.com"/>
</bean>

重新测试,发现可以访问到session中的数据。(注意要清空浏览器和redis数据库的数据)

单点登录

不同根域名下项目实现Session共享,

比如阿里巴巴这样的公司,它存在多个网站,天猫和淘宝都是他们的服务,但是是两个不同的网站。

当用户在淘宝登录之后,打开天猫也会自动登录。这就是session共享的单点登录。

单点登录(Single Sign On),简称为 SSO,是流行的企业业务整合的解决方案之一,SSO是指在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

第四章、Spring Session的执行流程(源码分析)

全局过滤器DelegatingFilterProxy

  1. 首先所有的页面请求都会被全局的过滤器org.springframework.web.filter.DelegatingFilterProxy过滤,这个过滤器是一个代理过滤器,他不执行真正的过滤逻辑,他代理了一个spring容器中的springSessionRepositoryFilter过滤器。

  1. 真正执行过滤逻辑的是SessionRepositoryFilter,其中@Bean注解相当于在xml配置文件中的

<bean id="springSessionRepositoryFilter" class="xx.xxx.xx.SessionRepositoryFilter">
      ........
</bean>

这个过滤器覆盖了原本servlet中request和response接口中定义操作session的方法,替换成了自己的session方法。

  1. 过滤的时候会执行一个finally语句块,在finally语句中提交一下session对象,将自己的这个session对象提交到redis数据库,以hash结构存储。

  1. spring session的配置类

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
    <!--设置session过期时间,单位是秒,默认是30分钟-->
    <property name="maxInactiveIntervalInSeconds" value="3600"/>
    <!--设置cookie的存放方式-->
    <property name="cookieSerializer" ref="defaultCookieSerializer"/>
</bean>

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

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

相关文章

Win10 突然蓝屏安全模式进不了,没有别的电脑和装机U盘,怎么把资料临时导出来?

环境: Win 10专业版 DELL 3490 移动硬盘/普通U盘 问题描述: Win10 突然蓝屏安全模式进不了,没有别的电脑和装机U盘,怎么把资料临时导出来?目前可以进入Win RE 疑难-高级选项 解决方案: 1.先插入,移动硬盘或者普通U盘 2.多重启几次,自动修复系统失败画面,点击高…

Linux嵌入式开发——压缩与解压缩

文章目录Linux嵌入式开发——压缩与解压缩一、前期准备二、Linux下的压缩格式三、gzip压缩工具1、gzip压缩文件2、gzip压缩文件夹四、bzip2压缩工具五、tar打包工具tar参数对.tar.bz2进行压缩和解压缩压缩解压缩对.tar.gz进行压缩和解压缩压缩解压缩六、其他格式的压缩和解压缩…

Qt扫盲-网络编程概述

网络编程概述一、Qt网络编程概述二、Qt对Http&#xff0c;FTP应用层协议支持三、TCP通信编程支持四、UDP通信编程支持五、主机信息的获取六、网络代理七、底层管理的支持一、Qt网络编程概述 Qt Network模块提供了允许我们编写TCP/IP客户端和服务器的类。它提供了低级类来完成基…

【Java寒假打卡】JavaWeb-Session

【Java寒假打卡】JavaWeb-Session概述常用的方法HttpSession的获取HttpSession的使用概述 常用的方法 HttpSession的获取 HttpSession的使用 在第一个Servlet中获取请求的用户名获取HttpSession对象将用户名设置到共享数据中在第二个Servlet中获取HttpSession对象获取共享数据用…

java8新特性

接口中默认方法修饰为普通方法&#xff0c;实现接口时不需要重写方法Lambda表达式Stream流并行流原理校验当前对象是否为null当前对象为null,设置默认值 接口中默认方法修饰为普通方法Lambda表达式使用Lambda表达式 依赖于函数接口 在接口中只能够允许有一个抽象方法在函数接…

SpringCloud笔记

2023年最新笔记&#xff0c;全文约 3 万字&#xff0c;蕴含 Spring Cloud 常用组件 Nacos、OpenFeign、Seata、Sentinel 等 〇、简介 什么是Spring Cloud&#xff1f; ​ Spring Cloud是一系列框架的有序集合&#xff0c;是一种基于微服务的分布式架构技术。它利用 Spring Boot…

HBuilder的安装与试用

准备把前端框架Layui仔细学习一遍&#xff08;虽然Layui已经过了最流行的时候&#xff0c;但是很多项目都在用它&#xff09;&#xff0c;在B站找了一套《Layui框架精讲全套视频教程》&#xff0c;视频作者实操Layui时用的工具很方便&#xff0c;从弹幕中看到说用的是HBuilder&…

Springcloud 笔记

微服务架构微服务架构是一种架构模式&#xff0c;它体长将单一应用程序划分成一组小的服务&#xff0c;服务之间相互协调&#xff0c;互相配合&#xff0c;为用户提供最终价值。每个服务运行在其独立的进程中&#xff0c;服务与服务之间采用轻量级的通信机制**(如HTTP)互相协作…

电商直通车主图设计教程

商直通车主图设计教程&#xff01;无门槛在线设计&#xff0c;零基础轻松入门的电商设计工具&#xff0c;轻松就能搞定的主图设计工具&#xff0c;下面跟着小编的设计教程&#xff0c;一起学习如何使用在线工具乔拓云轻松设计专属的商品直通车主图&#xff0c;在线模板轻松设计…

Cadence PCB仿真使用Allegro PCB SI生成延迟仿真报告及报告导读图文教程

🏡《Cadence 开发合集目录》   🏡《Cadence PCB 仿真宝典目录》 目录 1,概述2,生成报告3,报告导读4,总结1,概述 本文简单介绍使用Allegro PCB SI生成网络的延迟性能评估的报告的方法,及延迟报告要点导读。 2,生成报告 第1步,选择需要生成报告的网络,然后单击右…

深度估计算法原理与论文解读

论文地址: Monocular Depth Estimation Using Laplacian Pyramid-Based Depth Residuals | IEEE Journals & Magazine | IEEE Xplore 深度估计算法原理 1.深度估计任务概述 深度估计,即通过输入的彩色图像,获得每个像素点离相机距离的远近(热度图) ,热度图的深浅表…

Linux内核显卡驱动(LVDS)初探

目录 0. 前言 1. menuconfig 2. 编译报错与打补丁 3. 设备树与display-timings 4. 拓展&#xff1a;RGB24 0. 前言 这次的工作主要是把某项目设备上(iMX6DL)的内核版本从 4.19.x 升级到 5.15.32&#xff0c;是作为该项目整个BSP升级计划的一部分。 该内核升级工作移交给…

Spring Cloud Alibaba商城实战项目基础篇(day03)

五、后台管理 5.1、商品服务 5.1.1、三级分类 5.1.1.1、查询所有菜单与子菜单 我们需要维护所有菜单以及各种子菜单&#xff0c;子菜单里面可能还有子菜单&#xff0c;所以我们采用递归的方式进行书写。 我们先在CategoryController中修改list方法&#xff0c;让他以组装树…

Day868.索引(上) -MySQL实战

索引&#xff08;上&#xff09; Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于索引&#xff08;上&#xff09;的内容。 某一个 SQL 查询比较慢&#xff0c;分析完原因之后&#xff0c;可能就会说“给某个字段加个索引吧”之类的解决方案。但到底什么是索引&…

linux部署java项目cpu占用100%的排除故障

用top -c命令查看cpu占用高的进程 ![在这里插入图片描述](https://img-blog.csdnimg.cn/12af3f060fb84ce98b24c7247546b50b.png 发现cpu占用为99%的进程pid为24857 用top -Hp 24857查看cpu占用最高的线程 发现占用cpu97.3%的线程id为24926 将24926转为16进制 通过jstack查看进…

袋式除尘器—选型计算

1.处理气体量的计算计算袋式除尘器的处理气体时&#xff0c;首先要求出工况条件下的气体量&#xff0c;即实际通过袋式除尘器的气体量&#xff0c;并且还要考虑除尘器本身的漏风量。这些数据&#xff0c;应根据已有工厂的实际运行经验或检测资料来确定&#xff0c;如果缺乏必要…

Day09 - 子类父类多继承多层继承多态

1. 子类中访问父类中的私有属性和私有方法 如果想使用父类中的私有属性和私有方法,那么就需要在父类中,为这些私有的属性和方法,提供相应的公有的接口方法来间接访问2. 如何为父类中的属性进行初始化 在子类中如果定义了自己的初始化方法,那么这时父类的初始化方法就不会再执…

尚硅谷AJAX教程

优点&#xff1a;无需刷新页面获取数据&#xff0c;允许你根据用户事件来更新部分页面内容 缺点&#xff1a;没有浏览历史&#xff0c;不能回退&#xff0c;存在跨域&#xff0c;SEO不友好 原生XHR请求 get请求 <body><button>获取数据</button><scri…

弹性可微调,基于LCN光敏材料的触觉模拟系统

对于AR/VR体验来讲&#xff0c;体感、触觉模拟很重要&#xff0c;但现阶段还没有一种方便消费者使用、轻便的体感方案&#xff0c;因此Meta等公司不断在探索更好的体感技术。比如近期&#xff0c;Nature发表了一项来自荷兰埃因霍芬理工大学的新研究&#xff0c;该研究由Meta Re…

svg的path标签的d属性

<svgwidth"200"height"200"viewBox"0 0 200 200"style"border: 1px solid red"><pathd"M10 10 L110 10 L110 110 L10 110 Z"fill"none "stroke"green"></path></svg>运行效果…