SpringBoot集成SpringSession

本文介绍了Spring Session在Spring Boot项目中的集成步骤与自定义配置方法,对比了与传统session管理方式的区别,阐述了如何利用Spring Session实现分布式环境下的session共享。

目录

 

一、前言

1、为什么要用Spring-session

2、比较traditional-session方案和spring-session方案

3、JSR340规范与spring-session的透明继承

二、SpringBoot集成spring-session

1、导入依赖包

2、添加配置

3、添加请求测试类

4、运行代码,测试结果如下:

5、SpringBoot 整合 Spring Session 自定义配置介绍

三、小结

 


一、前言

在正式进行集成前,先说说spring-session。

1、为什么要用Spring-session

在传统单机web应用中,一般使用tomcat/jetty等web容器时,用户的session都是由容器管理。浏览器使用cookie中记录sessionId,容器根据sessionId判断用户是否存在会话session。这里的限制是,session存储在web容器中,被单台服务器容器管理

但是网站逐渐演变,分布式应用和集群是趋势(提高性能)。此时用户的请求可能被负载分发至不同的服务器,此时传统的web容器管理用户会话session的方式即行不通。除非集群或者分布式web应用能够共享session,尽管tomcat等支持这样做。但是这样存在以下两点问题:

  • 需要侵入web容器,提高问题的复杂
  • web容器之间共享session,集群机器之间势必要交互耦合

基于这些,必须提供新的可靠的集群分布式/集群session的解决方案,突破traditional-session单机限制(即web容器session方式,下面简称traditional-session),spring-session应运而生。

看看spring官网上对spring-session的介绍:

Spring Session提供了用于管理用户会话信息的API和实现。
Spring Session使得支持集群会话变得微不足道,而不依赖于特定于应用程序容器的解决方案。它还提供透明集成:
    HttpSession - 允许以应用程序容器(即Tomcat)中立的方式替换HttpSession,支持在头文件中提供会话ID以使用RESTful API
    WebSocket - 提供在接收WebSocket消息时保持HttpSession活动的能力
    WebSession - 允许以应用程序容器中立方式替换Spring WebFlux的WebSession

2、比较traditional-session方案和spring-session方案

下图展示了traditional-session和spring-session的区别

传统模式中,当request进入web容器,根据reqest获取session时,如果web容器中存在session则返回,如果不存在,web容器则创建一个session。然后返回response时,将sessonId作为response的head一并返回给客户端或者浏览器。

但是上节中说明了traditional-session的局限性在于:单机session。在此限制的相反面,即将session从web容器中抽出来,形成独立的模块,以便分布式应用或者集群都能共享,即能解决。

spring-session的核心思想在于此:将session从web容器中剥离,存储在独立的存储服务器中。目前支持多种形式的session存储器:Redis、Database、MogonDB等。session的管理责任委托给spring-session承担。当request进入web容器,根据request获取session时,由spring-session负责存存储器中获取session,如果存在则返回,如果不存在则创建并持久化至存储器中。

3、JSR340规范与spring-session的透明继承

JSR340是Java Servlet 3.1的规范提案,其中定义了大量的api,包括:servlet、servletRequest/HttpServletRequest/HttpServletRequestWrapper、servletResponse/HttpServletResponse/HttpServletResponseWrapper、Filter、Session等,是标准的web容器需要遵循的规约,如tomcat/jetty/weblogic等等。

在日常的应用开发中,develpers也在频繁的使用servlet-api,比如:

以下的方式获取请求的session:

HttpServletRequest request = ...
HttpSession session = request.getSession(false);

其中HttpServletRequest和HttpSession都是servlet规范中定义的接口,web容器实现的标准。那如果引入spring-session,要如何获取session?

  • 遵循servlet规范,同样方式获取session,对应用代码无侵入且对于developers透明化
  • 全新实现一套session规范,定义一套新的api和session管理机制

两种方案都可以实现,但是显然第一种更友好,且具有兼容性。spring-session正是第一种方案的实现。

实现第一种方案的关键点在于做到透明和兼容

  • 接口适配:仍然使用HttpServletRequest获取session,获取到的session仍然是HttpSession类型——适配器模式
  • 类型包装增强:Session不能存储在web容器内,要外化存储——装饰模式

让人兴奋的是,以上的需求在Servlet规范中的扩展性都是予以支持!Servlet规范中定义一系列的接口都是支持扩展,同时提供Filter支撑扩展点。建议阅读《JavaTM Servlet Specification》。

二、SpringBoot集成spring-session

说明:

  1. 这篇文章是基于springBoot2.0进行集成的。
  2. spring-session模式中session的持久化有3种,上面提到了,这里采用redis方式进行持久化。所以,在整合前,请先确保自己的机子上安装了redis.
  3. 请确保有可运行的搭建好的springBoot项目

1、导入依赖包

SpringBoot 和 Spring Session 整合的配置需要引入2个 start依赖:

  • spring-session-data-redis
  • spring-boot-starter-data-redis

具体代码如下:

  <!--导入springsession依赖包-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>

2、添加配置

在application.yml中添加redis配置:

spring:
  #配置redis
  redis:
    port: 6379
    host: localhost
    database: 0
server:
  port: 8081

3、添加请求测试类

package com.example.springsession;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * spring session测试控制类
 */
@RestController
public class HelloController {
   
    /**
     * 测试--设置session值
     * @param request
     * @param name
     * @return
     */
    @GetMapping("/set/{name}")
    public String  testSession(HttpServletRequest request, @PathVariable(value = "name") String name ) {
        HttpSession httpSession = request.getSession();
        httpSession.setAttribute("name", name);
        return "sessionId="+httpSession.getId();
    }

    /**
     * 测试--获取session值
     * @param request
     * @return
     */
    @GetMapping("/getName")
    public String getSession(HttpServletRequest request) {
        String name = (String) request.getSession().getAttribute("name");
        int port = request.getServerPort();
        int port2 = request.getLocalPort();

        return "sessionId=" + request.getSession().getId()
                + "      name==" + name + "request.getServerPort()==" + port +
                "===========request.getLocalPort()====" + port2;
    }
}

4、运行代码,测试结果如下:

5、SpringBoot 整合 Spring Session 自定义配置介绍

在快速整合的介绍中 我们使用都是默认的配置。如果你想自定义定义 Session 过期时间 、session的刷新模式 、存储Session的命名空间。可以通过在 application.properties 中进行配置。

具体配置介绍如下:

  • spring.session.store-type=redis

    设置 Spring Session 使用 Redis 进行存储。默认配置就是 redis

  • spring.session.timeout=10m
    设置 Spring Session 的过期时间。如果不指定单位模式是 s。
    也可以通过在启动类上声明@EnableRedisHttpSession进行配置。
    例如:@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3600)

  • spring.session.redis.flush-mode=on_save

    session刷新模式,有2中

    1. on_save
      保存时刷新,即响应结束后刷新。默认是 on_save
    2. immediate
      实时刷新

    也可以通过在启动类上声明@EnableRedisHttpSession进行配置。
    例如:@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.ON_SAVE)

  • spring.session.redis.namespace=redis:session

    存储 Session的命名空间,默认是spring:session。

    通过 Redis Desktop Manager 可以查看存储到Redis中的session信息的key都是以
    spring:session打头的。

也可以通过在启动类上声明@EnableRedisHttpSession进行配置。
例如:@EnableRedisHttpSession(redisNamespace=“xxxx”)

三、小结

通过在 SpirngBoot 项目中引入Spring Session 和 SpringBoot 整合 Redis 的 start 依赖,我们可以快速搭建分布式 Session 环境,同时也可以在 application.yml中自定义 Session 的过期时间、命名空间、刷新模式的配置。

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值