Spring +Spring Session+redis+ngiux实现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也可以,使用ip_hash策略。


【Nginx】实现负载均衡的几种方式


在使用Nginx的ip_hash策略时候,每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,也可以解决session的问题。

Spring官方介绍

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的请看这里: linux上Nginx的安装教程详解

没有配置Redis的请看这里:linux环境安装Redis

配置好了上面的环境,后下面开始正式的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.8</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">
	<display-name>springsession</display-name>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:spring/application-session.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<servlet>
		<servlet-name>SpringDispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextClass</param-name>
			<param-value>
				org.springframework.web.context.support.AnnotationConfigWebApplicationContext
			</param-value>
		</init-param>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>com.it</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>SpringDispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<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>
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
</web-app>

DelegatingFilterProxy将通过springSessionRepositoryFilter的名称查找Bean并将其转换为过滤器。对于调用DelegatingFilterProxy的每个请求,也将调用springSessionRepositoryFilter。

3.Xml的配置

添加了必要的依赖之后,我们需要创建相应的Spring配置。Spring配置是要创建一个Servlet过滤器,它用Spring Session支持的HttpSession实现来替换容器本身HttpSession实现。这一步也是Spring Session的核心。在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/>
    
    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
   
    <bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"/>

</beans>

上述代码注释:

LettuceConnectionFactory实例是配置Redis的ConnectionFactory,查看源代码可以看到,默认的Redis链接配置为:

因此,如果有自己的Redis配置,请修改,例如下边的配置:

<bean class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"> 
<property name="hostName" value="192.168.1.149"/> 
<property name="port" value="6379"/> 
<property name="password" value="123456"/>
</bean>

4、springmvc配置文件

package com.it.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan(basePackages="com.it")
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{

	@Bean
	public ViewResolver getViewResolver(){
		InternalResourceViewResolver resolver = new InternalResourceViewResolver();
		resolver.setPrefix("/WEB-INF/views/");
		resolver.setSuffix(".jsp");
		return resolver;
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
	}

	
}

5.测试代码

新建 SpringSessionController.java

@Controller
@RequestMapping(value = "/spring/session")
public class SpringSessionController {

    @RequestMapping(value = "/")
    public ModelAndView test(HttpServletResponse response) throws IOException {
        return new ModelAndView("home");
    }

    @RequestMapping(value = "/setSession.do", method = RequestMethod.GET)
    public void setSession(HttpServletRequest request, HttpServletResponse response) {
        String name = request.getParameter("name");
        String value = request.getParameter("value");
        request.getSession().setAttribute(name, value);
    }

    @RequestMapping(value = "/getSession.do", method = RequestMethod.GET)
    public void getInterestPro(HttpServletRequest request, HttpServletResponse response) {
        String name = request.getParameter("name");
        System.out.println("------" + request.getSession().getAttribute(name));
    }

    @RequestMapping(value = "/removeSession.do", method = RequestMethod.GET)
    public void removeSession(HttpServletRequest request, HttpServletResponse response) {
        String name = request.getParameter("name");
        request.getSession().removeAttribute(name);
    }

}

 

效果演示

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

2.配置Nginx,启动Nginx

Nginx的配置,权重方式(或轮询):

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    
    keepalive_timeout  65;

    #gzip  on;
     upstream local_tomcat {
     server localhost:8080 weight=1;
     server localhost:8090 weight=1;  
    }
    server {
        listen       80;
        server_name  localhost:8080;

        location / {
           proxy_pass http://local_tomcat;
          
        }

   

3.启动Tomcat1和Tomcat2

将上面搭建好的项目放入两个Tomcat中,分别启动。

http://192.168.0.147:8090/springsession/spring/session/getSession

http://192.168.0.147:8080/springsession/spring/session/getSession

保证两个tomcat能正常访问

 

4、使用Nginx负载均衡均验证Session是否共享成功,

直接访问Nginx路径:http://192.168.0.147/springsession/spring/session/getSession,

 

刷新页面,变成8090服务器,值可以取到,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

验证成功!

云卓遥控器+DIY高清摄像机的方案(完美接入原系统) 发云卓H16 1080P数图控三合一10公里 其中它月 阅读详情

相关推荐

【UE4】Hierarchical Instanced Static Mesh——一种速度优于Spawn的实例化物体组件

最近需要在场景中实例出很多个相同的模型,位置也很有规律,并且要对它的位置信息进行更新。 但是一个个拖进去实在太麻烦,就发现了Spawn Actor这个蓝图方法,可以实例一个蓝图类在场景中。 但是由于数量较大,实例化的速度太慢,这时发现了一个神奇的组件——Hierarchical Instanced Static Mesh。 新建一个蓝图类,添加该组件,在细节里添加你要实例化的模型对象。 ...

ColorGalaxy 1万+

Spring之RedisSession详解

Spring redisSession

weixin_42132854的博客 5995

适合小白的超详细yolov8环境配置+实例运行教程,从零开始教你如何使用yolov8训练自己的数据集(Windows+conda+pycharm)

yolov8源码下载地址:GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLiteyolov8使用文档: Home - Ultralytics YOLOv8 Docs教学视频参考: 包会!YOLOv8训练自己的数据集_哔哩哔哩_bilibili先用conda prompt创建一个虚拟环境,我的叫yolov8, python版本用3.10 源码地址:GitHub - ul

CV在读 25万+

springsession原理及redis缓存处理

1 Redis 中数据 通过springsession存储了用户的session数据,如下: "spring:session:expirations:1634214780000" 记录了失效时间是哪个session的,指向下面的key "spring:session:sessions:6317e334-90e9-4f55-a1f5-07492a8c8b2a" 保存了session相关信息(创建时间,session保存的对象信息,最大超时时间:默认1800秒,最后的修改时间) "spring:

asmall_cat的博客 4854

语义通信理论必看论文:Towards a Theory of Semantic Communication

了解语义通信发展必看的一篇文章

一去不复返的通信er 3926

【超详细】基于YOLOv8的PCB缺陷检测

印刷电路板(PCB)瑕疵数据集:是一个公共的合成PCB数据集,由北京大学发布,其中包含1386张图像以及6种缺陷(缺失孔,鼠标咬伤,开路,短路,杂散,伪铜),用于检测,分类和配准任务。本文我们选取了其中适用与检测任务的693张图像,随机选择593张图像作为训练集,100张图像作为验证集。

weixin_45679938的博客 2万+

SpringBoot 全家桶 | SpringSession + Redis实现会话共享

官方介绍 Spring Session 提供了一个 API 和实现,用于管理用户的会话信息,同时使其在不依赖于特定于应用程序容器的解决方案的情况下,可以轻松地支持集群会话。它还提供了透明的集成: HttpSession 允许以中立的方式替换应用程序容器(即 Tomcat)中的HttpSession,并支持在 Headers 中提供会话 ID 以与 RESTful API 一起使用。 WebSocket 能够在接收 WebSocket 消息时使HttpSession保持活动状态 WebSession 允许以

人生就是一个不断学习的过程 3255

RK3568-Linux-麒麟系统---更新制作麒麟rootfs

RK3568 Linux系统 麒麟国产麒麟镜像

qiuzw2003的博客 5360

SpringSession——redis

官方参考手册:https://docs.spring.io/spring-session/docs/2.2.1.RELEASE/reference/html5/#samples 整合redis手册: 1. 项目整合 1.1 依赖 <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artif.

武汉小喽啰 2874

利用自己的域名和cloudflare实现邮件转发(无限邮箱注册cursor使用账号) 保姆级图文

大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!发现你走远了@mzh原创作品,转载必须标注原文链接欢迎关注『发现你走远了』 专栏,持续更新中欢迎关注『发现你走远了』 专栏,持续更新中『未完待续』

MZH 413

SOME/IP协议详解「1.0·概述」

主要讲解什么是someip,

雪云飞星的博客 5367

【SpringBoot】31 Session + Redis 实战

org.springframework.data.redis.serializer.JdkSerializationRedisSerializer ,默认情况下,RedisTemplate 使用该数据列化方式。RedisTemplate#afterPropertiesSet() 方法,在 RedisTemplate 未设置序列化的情况下,使用 JdkSerializationRedisSerializer 作为序列化实现。

寻道书生的博客 2054

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

WW、forever的博客 195

【SpringBoot集成Redis + Session持久化存储到Redis】

本文主要介绍了SpringBoot如何集成redis,快速简单使用redis,及其一些redis的简单应用,例如存储session到redis,如有错误,恳请大佬指点!谢谢!

TheMyth142857的博客 4389

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SpringBoot 整合SpringSession 采用redis存储流程、SpringSession原理

SpringSession 整合以及工作原理

hh_lew的博客 1828

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

spring session通过redis存储,实现session共享

目录 前言 1 准备工作 1.1 spring框架的jar包 1.2 spring session的相关jar包 2 具体步骤 2.1 创建项目 2.2 spring mvc的配置 2.3 spring session的配置 2.4 web.xml的配置 3 测试 3.1 创建jsp测试文件 3.2 开始测试 前言 web开发中session一直都是做分布式集群应用时需...

叶梦 2万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

前端nginx部署-真的不是那么难

本文介绍了Nginx服务器的配置与使用指南。首先从官网下载稳定版本(如nginx-1.12.2),通过修改nginx.conf文件配置server模块,设置监听端口、服务器名称及文件路径映射。配置完成后,将前端项目打包放入指定目录即可访问。文章提供了常用Nginx命令(启动、关闭、重载等)和日志查看方法(access.log和error.log)。最后建议深入学习Nginx内置变量,如$remote_addr、$request等,这些变量在日志分析和请求处理中非常有用。

m0_66237295的博客 505

nginx网站服务

高性能:对http的并发连接的处理能力很高,单台物理服务器可支持30000-50000个并发请求。(在实际操作中,为了维持服务器的稳定,一般会设置在20000个左右)轻量级:ngiux软件很小,安装所需空间很小,是一个小服务小软件,可以支持高并发,稳定性强,对系统资源消耗低。

qq_51506982的博客 278

spring session + redis

spring session + redis 上面所说的第二种方式会与 tomcat 容器重耦合,如果我要将 web 容器迁移成 jetty,难道还要重新把 jetty 都配置一遍? 因为上面那种 tomcat + redis 的方式好用,但是会严重依赖于web容器,不好将代码移植到其他 web 容器上去,尤其是你要是换了技术栈咋整?比如换成了 spring cloud 或者是 spring bo...

一个跑不快胖子的博客 2934

分布式Session之使用Spring-Session & Redis实现

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34192732的博客 409

Spring Session + Redis 使用

由于http协议是无状态的协议,为了能够记住请求的状态,于是引入了Session和Cookie的机制。 Session是存在于服务器端的,在单体式应用中,他是由tomcat管理的,存在于tomcat的内存中。 当我们为了解决分布式场景中的session共享问题时,引入了redis,其共享内存,以及支持key自动过期的特性,非常契合session的特性,我们在企业开发中最常用的也就是这种模式。但是只...

shpunishment的博客 5021

分布式环境下的session 共享-基于spring-session组件和Redis实现

模拟在分布式环境下的,将用户的session信息存入到redis中,实现session信息共享。

雾林小妖的博客 1721

分布式session的问题(使用SpringSession和redis解决)

之前的代码在我们之后一台应用系统,所有操作都在一台Tomcat上,没有什么问题。当我们部署多台系统,配合Nginx的时候会出现用户登录的问题 原因 由于 Nginx 使用默认负载均衡策略(轮询),请求将会按照时间顺序逐一分发到后端应用上。 也就是说刚开始我们在 Tomcat1 登录之后,用户信息放在 Tomcat1 的 Session 里。过了一会,请求又被 Nginx 分发到了 Tomcat2 上,这时 Tomcat2 上 Session 里还没有用户信息,于是又要登录。 ............

qq_51269815的博客 1253

Spring Session:Redis序列化配置|Session事件监听

Spring Session:Redis序列化配置|Session事件监听。

席木木的博客 2550

SpringSession+redis解决分布式session不一致性问题

七、案例实战:SpringSession+redis解决分布式session不一致性问题 步骤1:加入SpringSession、redis的依赖包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE&lt

INGNIGHT的专栏 2171

Springboot 开发 -- Redis实现分布式Session

在微服务架构和分布式系统中,会话管理(Session Management)成为了一个挑战。传统的基于Servlet容器的会话管理方式在分布式环境下无法有效工作,因为用户请求可能会被分发到不同的服务器上,导致会话数据无法共享。为了解决这个问题,Spring Session提供了一种基于外部存储(如Redis)的会话管理方式,使得会话数据可以在多个服务器之间共享。

dazhong2012的专栏 2427
上一篇: Spring 注解@Value详解
下一篇: 【Nginx】Nginx详解
fmwind
博客等级 码龄24年 147粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值