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. 把对像生成json并存储到文件

    1.创建实体对像json import com.alibaba.fastjson.annotation.JSONField; import java.util.Date; public class S ...

  2. eclipse中经常用到的修改菜单项

    1.编写java程序时,书写一个类之后,要调用此类的某个方法时,点个点,此类的所有方法都会自动出现,然后再选择需要的那个方法即可: 2.鼠标放在一个类上面,关于此类的相关描述就会自动加载出来,要修改的 ...

  3. Luogu P2168 [NOI2015]荷马史诗

    题目 哈夫曼树的每个叶子结点都有一个权值(表示某数据的出现频率),且\(\sum dis_ival_i\)最小. 哈夫曼树中,权值和越大的集合离根节点越近. 而每个数据对应从根节点到该叶子结点的一种编 ...

  4. 18: vue-element-admin使用

    1.1 vue-element-admin使用 1.使用参考网站 1)官方演示环境: https://panjiachen.github.io/vue-element-admin/#/dashboar ...

  5. CSUST 8.4 早训

    ## Problem A A - Memory and Crow CodeForces - 712A 题意: 分析可得bi=ai+ai+1 题解: 分析可得bi=ai+ai+1 C++版本一 #inc ...

  6. Chrome开发者工具详解(四)之Elements、Console、Sources面板

    Elements面板 实时编辑DOM节点和CSS样式 双击DOM树视图里面的节点,可以实时编辑标签属性,修改的效果会立刻反应在浏览器里 点击右侧Style面板,可以实时修改CSS的属性值,这里面的所有 ...

  7. numpy.random.randn()和numpy.random.rand()

    1 numpy.random.rand() (1)numpy.random.rand(d0,d1,…,dn) rand函数根据给定维度生成[0,1)之间的数据,包含0,不包含1 dn表格每个维度 返回 ...

  8. 内存分析工具MAT(Memory Analyzer Tool)从安装到使用

    一.安装 首先,你得有一个Eclipse(因为MAT是Eclipse的插件) 然后,你要在Eclipse上安装MAT,步骤如下: 1.点击Help,Install New Soft,就出现了以下Ins ...

  9. Linux上进行常用软件的配置

    当拿到一个新的linux服务器的时候一般要经过以下5个配置    修改HOSTANME        vi /etc/sysconfig/network    修改HOSTNAME和IP的映射     ...

  10. mongo 数据库操作

    启动和关闭数据库 启动 # mongodb 默认使用执行 mongod 命令所处的盘的根目录下  /data/db 作为自己的数据存储目录 #   所以在第一次执行该命令之前先自己动手新建一个  /d ...