SpringBoot 集成 Spring Session

SpringBoot 集成 Spring Session

應該講解清楚,爲何要使用 Redis 進行 Session 的管理。java

Session 複製又是什麼概念。git

Spring Session 在汪雲飛老師的書裏的介紹是:github

Spring Session:提供一個 API 及實現來管理用戶會話信息。web

咱們能夠這樣理解,原來在 Tomcat 服務器中存在的 Session 統一放置在 Redis 中進行管理。
這樣在服務器集羣的時候,就不會出現狀態不一致的狀況。(這一步還需要描述詳細一些,最好把本身實驗的過程展現一下)。redis

第 1 步:添加依賴

除了 SpringBoot 最最基礎的依賴 spring-boot-starter-webspring

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

之外,咱們還需要添加 spring-boot-starter-data-redisspring-sessionshell

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 服務的支持。apache

第 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;
    }

}

咱們執行tomcat

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

相關文章
相關標籤/搜索