SpringBoot 集成 Spring Session

应该讲解清楚,为什么要使用 Redis 进行 Session 的管理。

Session 复制又是什么概念。

Spring Session 在汪云飞老师的书里的介绍是:

Spring Session:提供一个 API 及实现来管理用户会话信息。

我们可以这样理解,原来在 Tomcat 服务器中存在的 Session 统一放置在 Redis 中进行管理。

这样在服务器集群的时候,就不会出现状态不一致的情况。(这一步还须要描述详细一些,最好把自己实验的过程展示一下)。

第 1 步:添加依赖

除了 SpringBoot 最最基础的依赖 spring-boot-starter-web

compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.2.RELEASE'

以外,我们还须要添加 spring-boot-starter-data-redisspring-session

compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '1.5.2.RELEASE'
compile group: 'org.springframework.session', name: 'spring-session', version: '1.3.0.RELEASE'

另外,我们还须要 Redis 服务的支持。

第 2 步:添加 Spring Session 相关的配置

  1. 配置 Spring Session 使用 Redis 来进行统一管理,以及 Redis 的主机和端口号
spring.session.store-type=redis

spring.redis.host=localhost
spring.redis.port=6388
  1. 配置 Session 失效的时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 24 * 60 * 60)
public class SessionConfig {
}

下面编写测试代码。

@RestController
public class SessionController { // 用于测试 SpringBoot 容器是否启动
// http:localhost:8080/test
@RequestMapping("/test")
public String test(){
return "PING OK";
} // http:localhost:8080/put?key=name&value=liwei
@RequestMapping("/put")
public String put(HttpSession session,
@RequestParam("key") String key,@RequestParam("value") String value){
session.setAttribute(key,value);
return "PUT OK";
} // http:localhost:8080/get?key=name
@RequestMapping("/get")
public String get(HttpSession session,
@RequestParam("key") String key){
String value = (String) session.getAttribute(key); if(value == null || "".equals(value)){
return "NO VALUE GET";
}
return value;
} }

我们执行

gradle clean build

然后再执行

java -jar build/libs/SpringBootSessionDemo-1.0-SNAPSHOT.jar --server.port=8081
java -jar build/libs/SpringBootSessionDemo-1.0-SNAPSHOT.jar --server.port=8082
java -jar build/libs/SpringBootSessionDemo-1.0-SNAPSHOT.jar --server.port=8083

启动 3 台服务器。

实验的思路是这样的:在 1 台服务器上的 Session 中放入 key 和 value,在另外两台服务器上都可以获得 key 对应的 value。

第 1 步:请求

http://localhost:8081/put?key=age&value=24

第 2 步:

http://localhost:8082/get?key=age

http://localhost:8083/get?key=age

此时,在两台服务器 8082 和 8083 上可以看到我们在服务器 8081 的 Session 中放入的数据。

第 3 步:登录 Redis 服务端,情况 Redis 的缓存,再次执行第 2 步的请求,发现不能获得 Session 的数据。

redis-cli -p 6388
flushdb

至此,就说明此时 3 台服务器上的 Session 都由 Redis 来管理了。

如果我们把关于 Spring Session 和 Redis 的配置都去掉的话,就会发现在 1 台服务器上的 Session 的设置和获取都只能在这台服务器上完成。

补充说明:在 Gradle 项目中要通过使用 spring-boot 这个插件,才能使打出来的 jar 包可以执行 java -jar 开始运行。

配置方法:

allprojects {
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
}
} buildscript { ext {
springBootVersion = '1.5.2.RELEASE'
} repositories {
jcenter()
mavenLocal()
mavenCentral()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url "http://repo.spring.io/release" }
maven { url "http://repo.spring.io/milestone" }
maven { url "http://repo.spring.io/snapshot" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "com.github.adrianbk:gradle-jvmsrc-plugin:0.6.1"
}
}

此时,就可以使用 spring-boot 插件了。

apply plugin: 'spring-boot'
org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.liwei.model.User]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:93) ~[spring-data-redis-1.8.1.RELEASE.jar!/:na]
at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:171) ~[spring-data-redis-1.8.1.RELEASE.jar!/:na]
at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129) ~[spring-data-redis-1.8.1.RELEASE.jar!/:na]
at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86) ~[spring-data-redis-1.8.1.RELEASE.jar!/:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80) ~[spring-session-1.3.0.RELEASE.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) ~[tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar!/:8.5.11]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.liwei.model.User]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:68) ~[spring-core-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:35) ~[spring-core-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:91) ~[spring-data-redis-1.8.1.RELEASE.jar!/:na]
... 33 common frames omitted
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.liwei.model.User]
at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43) ~[spring-core-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:63) ~[spring-core-4.3.7.RELEASE.jar!/:4.3.7.RELEASE]
... 35 common frames omitted

User 类要实现序列化接口。

http://localhost:8081/put/user

http://localhost:8082/put/user

http://localhost:8083/put/user

这篇文章涉及到的源代码可以在我的 GitHub 上下载:https://github.com/weimingge14/SpringBootSessionDemo

SpringBoot 集成 Spring Session的更多相关文章

  1. springboot集成Spring Session

    10.1 分布式集群环境下的集成(同域名.同项目) 10.1.1        创建SpringBoot的web支持项目07-springboot-session 创建项目 10.1.2        ...

  2. SpringBoot集成Spring Security(7)——认证流程

    文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...

  3. SpringBoot集成Spring Security(6)——登录管理

    文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...

  4. SpringBoot集成Spring Security(4)——自定义表单登录

    通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...

  5. Springboot集成Spring Batch

    Spring官网 (https://spring.io/projects/spring-batch#overview)对Spring  Batch的解释: 一个轻量级的.全面的批处理框架,用于开发对企 ...

  6. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  7. SpringBoot集成Spring Security(5)——权限控制

    在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...

  8. SpringBoot集成Spring Security(2)——自动登录

    在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...

  9. Spring boot集成spring session实现session共享

    最近使用spring boot开发一个系统,nginx做负载均衡分发请求到多个tomcat,此时访问页面会把请求分发到不同的服务器,session是存在服务器端,如果首次访问被分发到A服务器,那么se ...

随机推荐

  1. [转帖]探秘华为(二):华为和H3C(华三)的分道扬镳

    探秘华为(二):华为和H3C(华三)的分道扬镳 https://baijiahao.baidu.com/s?id=1620781715767053734&wfr=spider&for= ...

  2. 【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况

    SQL Server 操作系统(SQLOS)负责管理特定于SQL Server的操作系统资源. 其中相关的动态管理试图sys.dm_os_ring_buffers将被标识为仅供参考.不提供支持.不保证 ...

  3. 【PDF】手写字与识别字重叠

    [PDF]手写字与识别字重叠 前言 同学平时上课用iPad记笔记,考试之前导出为PDF发给我后,我用PDF打开,发现可以直接Ctrl+F搜索一些词语.一直不知道是怎么做到的,毕竟里面的字都是手写的,不 ...

  4. 高性能迷你React框架anujs1.1.3发布

    anujs现在只差一个组件(mention)就完全支持阿里的antd UI库了.一共跑通346个测试, 应该是全世界最接近官方React的迷你框架了. 以后的工作就是把React16的一些新特性支持了 ...

  5. CSUST 8.3 早训

    A - Settlers' Training CodeForces - 63B 题意 给你一串数字,相同的数字为一组,每次可以给一组中的一个数字加一,问这一串数字全变成K需要多少步? 题解 模拟 C+ ...

  6. 【学习总结】快速上手Linux玩转典型应用-第2章-linux简介

    课程目录链接 快速上手Linux玩转典型应用-目录 目录 1. 什么是Linux 2. Linux能够做什么事情 3. Linux的学习方法 4. 忘掉Windows的所有东西 1. 什么是Linux ...

  7. js/nodejs导入Excel相关

    导入示例如下: Excel可设置单元格的数字显示格式,特别的,常规格式下,会根据列宽缩进显示. 实际中,有时需要导入实际值,有时需要导入显示值. 而B2的显示值,由于跟列宽相关,目前未找到任何软件,可 ...

  8. 【React -- 9/100】 抽离顶部导航栏 - [组件复用]

    今天写的页面中需要重复使用到顶部导航栏,所以把顶部导航栏抽离出来 考虑复用组件的健壮性,使用PropTypes校验,可以自定义一个click事件 JSX import React from " ...

  9. iOS开发之详解剪贴板

    关于UIMenuController的用法例子 今天终于搞明白了UIMenuController显示的相关内容,把源代码分享给大家! 要正常显示菜单,必须做到以下几点:1. -(BOOL)canBec ...

  10. UIAlertView, UIAlertViewController

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController 在实现视图控制器间的过渡动画效果和自适应设备尺 ...