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. ContextLoaderListener错误

    在web.xml中添加如下配置 <context-param> <param-name>contextConfigLocation</param-name> < ...

  2. [转帖]100G QSFP28与CFP,CFP2,CFP4光模块的比较

    100G QSFP28与CFP,CFP2,CFP4光模块的比较 https://www.eefocus.com/etulink/blog/17-09/423967_5c520.html 数据中心网络发 ...

  3. hive数据去重

    Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能 hive的元数据存储:通常是存储在关系数据库如 mysql(推荐) , derby(内嵌 ...

  4. PHP MVC结构系统架构设计

    今天研究了下PHP MVC结构,所以决定自己写个简单的MVC,以待以后有空再丰富.至于什么MVC结构,其实就是三个Model,Contraller,View单词的简称,,Model,主要任务就是把数据 ...

  5. 又一Tab切换效果(js实现)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. DataTable中如何去除重复的项 (获得某个字段中的不重复项)

    就是获取DataTable中某一列的值,因为从数据库中检索数据时,按照2个字段进行分组,而要获得的那一列刚好在分组这两列中,所以该列的值必然有重复,于是就想到了去除重复,有了思路以后在网上看了一些方法 ...

  7. 微信小程序css篇----flex模型

    一.Flex布局是什么? Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为Flex布局. .box{displ ...

  8. iOS APP 国际化

    pp Store 中很多流行的应用程序有多种语言版本.虽然这些应用程序可能因为很多因素而变得流行,但是具有多种本地化版本,肯定是其中一个因素.越多的人可以理解并使用您的应用程序,潜在的买家也就越多. ...

  9. PAT Advanced 1001 A+B Format (20 分)

    Calculate a+b and output the sum in standard format -- that is, the digits must be separated into gr ...

  10. PAT Basic 1026 程序运行时间 (15 分)

    要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间.这个时间单位是 clock ...