百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

【第一篇】Spring-Session实现Session共享入门教程

yuyutoo 2024-10-12 01:39 5 浏览 0 评论

任何一种技术的出现,都是来解决特定的问题的!

本篇开始学习Spring-Session相关的一些知识学习整理,让我们开始吧!

Spring-Session介绍

  1. Spring-Session使用的场景?

HttpSession是通过Servlet容器进行创建和管理的,在单机环境中。通过Http请求创建的Session信息是存储在Web服务器内存中,如Tomcat/Jetty。

假如当用户通过浏览器访问应用服务器,session信息中保存了用户的登录信息,并且session信息没有过期失,效那么用户就一直处于登录状态,可以做一些登录状态的业务操作!

但是现在很多的服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不同的服务器上,通过LVS或者Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的Http请求将有可能被分发到不同的web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。那么问题就来了,如何保证不同的web站点能够共享同一份session数据呢?

假如用户在发起第一次请求时候访问了A站点,并在A站点的session中保存了登录信息,当用户第二次发起请求,通过负载均衡请求分配到B站点了,那么此时B站点能否获取用户保存的登录的信息呢?答案是不能的,因为上面说明,Session是存储在对应Web服务器的内存的,不能进行共享,此时Spring-session就出现了,来帮我们解决这个session共享的问题!

  1. 如何进行Session共享呢?

简单点说就是请求http请求经过Filter职责链,根据配置信息过滤器将创建session的权利由tomcat交给了Spring-session中的SessionRepository,通过Spring-session创建会话,并保存到对应的地方。

实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis,Mongo)中,

而上面说的使用Nginx也可以,使用iphash策略。 【Nginx】实现负载均衡的几种方式 在使用Nginx的iphash策略时候,每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,也可以解决session的问题。

  1. Spring官方介绍
  2. Why Spring Session & HttpSession?

Spring会话提供了与HttpSession的透明集成,允许以应用程序容器(即Tomcat)中性的方式替换HttpSession,但是我们从中得到了什么好处呢?

  • 集群会话——Spring会话使支持集群会话变得微不足道,而不需要绑定到应用程序容器的特定解决方案。
  • 多个浏览器会话——Spring会话支持在单个浏览器实例中管理多个用户会话(也就是多个经过验证的帐户,类似于谷歌)。
  • RESTful api——Spring会话允许在header中提供会话id以使用RESTful api。
  • Spring Session & WebSockets的完美集成。

项目搭建

整个项目的整体骨架:

基于XML配置方式的Spring Session

本次只讲解xml配置方式,javaConfig配置可以参考官方文档:Spring Java Configuration

环境说明

本次项目需要用户Nginx和Redis,如果没有配置Nginx的请看这里: Windows上Nginx的安装教程详解

没有配置Redis的请看这里:Redis——windows环境安装Redis和Redis sentinel部署教程

配置好了上面的环境,后下面开始正式的Spring-session搭建过程了!

1.添加项目依赖

首先新建一个Maven的Web项目,新建好之后在pom文件中添加下面的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>org.spring</groupId>
 <artifactId>learn-spring-session</artifactId>
 <version>1.0-SNAPSHOT</version>
 <packaging>war</packaging>
 <name>First Learn Spring Session</name>
 <properties>
 <jdk.version>1.7</jdk.version>
 <spring.version>4.3.4.RELEASE</spring.version>
 <spring-session.version>1.3.1.RELEASE</spring-session.version>
 </properties>
 <dependencies>
 <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
 <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>javax.servlet-api</artifactId>
 <version>3.0.1</version>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.session</groupId>
 <artifactId>spring-session-data-redis</artifactId>
 <version>${spring-session.version}</version>
 <type>pom</type>
 </dependency>
 <dependency>
 <groupId>biz.paluch.redis</groupId>
 <artifactId>lettuce</artifactId>
 <version>3.5.0.Final</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>${spring.version}</version>
 </dependency>
 </dependencies>
</project>

2.web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
 xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath*:spring/*xml</param-value>
 </context-param>
 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <!--DelegatingFilterProxy将查找一个Bean的名字springSessionRepositoryFilter丢给一个过滤器。为每个请求
 调用DelegatingFilterProxy, springSessionRepositoryFilter将被调用-->
 <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>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>ERROR</dispatcher>
 </filter-mapping>
 <welcome-file-list>
 <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
</web-app>

3.Xml的配置

在resources 下面新建一个xml,名词为 application-session.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 <context:annotation-config/>
 <!--创建一个Spring Bean的名称springSessionRepositoryFilter实现过滤器。
 筛选器负责将HttpSession实现替换为Spring会话支持。在这个实例中,Spring会话得到了Redis的支持。-->
 <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
 <!--创建了一个RedisConnectionFactory,它将Spring会话连接到Redis服务器。我们配置连接到默认端口(6379)上的本地主机!-->
 <bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>
</beans>

4.测试代码

新建 LoginServlet.java

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
 @Override
 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
 HttpServletRequest request = (HttpServletRequest) req;
 HttpServletResponse response = (HttpServletResponse) res;
 request.getSession().setAttribute("testKey", "742981086@qq.com");
 request.getSession().setMaxInactiveInterval(10*1000);
 response.sendRedirect(request.getContextPath() + "/session");
 }
}

新建 SessionServlet.java

@WebServlet("/session")
public class SessionServlet extends HttpServlet {
 @Override
 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
 HttpServletRequest request = (HttpServletRequest) req;
 HttpServletResponse response = (HttpServletResponse) res;
 System.out.println(request.getRemoteAddr());
 System.out.print(request.getRemoteHost() + " : " + request.getRemotePort());
 String sesssionID = request.getSession().getId();
 System.out.println("-----------tomcat2---sesssionID-------" + sesssionID);
 String testKey = (String)request.getSession().getAttribute("testKey");
 System.out.println("-----------tomcat2-testKey-------" + testKey);
 PrintWriter out = null;
 try {
 out = response.getWriter();
 out.append("tomcat2 ---- sesssionID : " + sesssionID);
 out.append("{\"name\":\"dufy2\"}" + "\n");
 out.append("tomcat2 ----- testKey : " + testKey + "\n");
 }catch (Exception e){
 e.printStackTrace();
 }finally {
 if(out != null){
 out.close();
 }
 }
 }
}

效果演示

1.启动Redis,默认端口6379就行!

2.配置Nginx,启动Nginx

Nginx的配置,轮询方式:

#user nobody;
worker_processes 1;
events{
 worker_connections 1024;
 }
http{
 upstream myproject {
 server 127.0.0.1:8888;
 server 127.0.0.1:9999;
 }
 server {
 listen 8080;
 server_name localhost;
 location / {
 proxy_pass http://myproject;
 }
 }
}

3.启动Tomcat1和Tomcat2

将上面搭建好的项目放入两个Tomcat中,分别启动。使用Nginx负载均衡均验证Session是否共享成功!

tomcat1 : http://localhost:8888/

tomcat2 : http://localhost:9999/

访问 http://localhost:8080/ 可以看到,每次刷新页面,请求都分发到不同的Tomcat里面,如图

然后使用 http://localhost:8080/login 看到地址栏重定向到/session .发现浏览器返回了数据,进入tomcat2中,然后再次刷新请求进入了tomcat1,发现tomcat2中和tomcat1 sessionId一样,并且在tomcat1中存的testKey,在Tomcat2中也可以获取,不仅SessionId可以共享,其他一些数据也可以进行共享!

如何在Redis中查看Session数据,可以使用命令,或者在Windows的RedisDesktopManager中查看!

key的简单介绍说明:

# 存储 Session 数据,数据类型hash
Key:spring:session:sessions:XXXXXXX
# Redis TTL触发Session 过期。(Redis 本身功能),数据类型:String
Key:spring:session:sessions:expires:XXXXX
#执行 TTL key ,查看剩余生存时间
#定时Job程序触发Session 过期。(spring-session 功能),数据类型:Set
Key:spring:session:expirations:XXXXX

验证成功!

总结

Spring-Session在实际的项目中使用还是比较广泛的,本次搭建采用最简单的配置,基本都是采用官方文档中默认的方式,因为是入门的教程就没有写的很复杂,后面慢慢深入!期待后续的教程吧!

参考文章

使用Spring Session和Redis解决分布式Session跨域共享问题57406162

学习Spring-Session+Redis实现session共享

利用spring session解决共享Session问题

本系列教程

【入门】分布式Session一致性入门简介

【第一篇】Spring-Session实现Session共享入门教程

【第二篇】Spring-Session实现Session共享Redis集群方式配置教程

【第三篇】Spring-Session实现Session共享实现原理以及源码解析


谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你每天开心愉快!


不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

愿你我在人生的路上能都变成最好的自己,能够成为一个独挡一面的人

? 每天都在变得更好的阿飞云

相关推荐

史上最全的浏览器兼容性问题和解决方案

微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...

平面设计基础知识_平面设计基础知识实验收获与总结
平面设计基础知识_平面设计基础知识实验收获与总结

CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...

2025-02-21 16:01 yuyutoo

写作排版简单三步就行-工具篇_作文排版模板

和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...

写一个2048的游戏_2048小游戏功能实现

1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...

今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……

  最近的天气暖和得让很多小伙伴们喊“热”!!!  昨天的气温到底升得有多高呢?你家有没有榜上有名?...

CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式

之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...

柠檬科技肖勃飞:大数据风控助力信用社会建设

...

你的自我界限够强大吗?_你的自我界限够强大吗英文

我的结果:A、该设立新的界限...

行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?

行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...

让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华

去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...

2025-02-21 16:00 yuyutoo

今年国家综合性消防救援队伍计划招录消防员15000名

记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...

一起盘点最新 Chrome v133 的5大主流特性 ?

1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...

竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使

style="text-align:center;"data-mce-style="text-align:...

学物理能做什么?_学物理能做什么 卢昌海

作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...

你不知道的关于这只眯眼兔的6个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: