1

title: spring-session实现分布式集群session的共享
tags: springboot,spring,session共享

grammar_cjkRuby: true

**本文使用springboot实现session共享,基于spring session实现
想使用基于容器的session共享请搜索其他文章

本文不讲解基础环境搭建,需要使用idea、maven、springboot等相关知识点,不做介绍

未做session共享

整体项目结构

基础结构

基础代码:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xiang.springboot.demo</groupId>
    <artifactId>springboot-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>springboot-demo</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

SpringbootDemoApplication.java

package com.xiang.springboot.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.context.ServletContextAware;

import javax.servlet.ServletContext;

@SpringBootApplication
public class SpringbootDemoApplication implements ServletContextAware {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootDemoApplication.class, args);
    }

    @Override
    public void setServletContext(ServletContext context) {
        String ctx = context.getContextPath();
        System.out.println("ctx=" + ctx);
        context.setAttribute("ctx", ctx);
    }
}

TestController.java

package com.xiang.springboot.demo.module1.controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

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

@Controller
@RequestMapping("/module1")
public class TestController {
    @GetMapping("/page1")
    public String page1(HttpServletRequest request, HttpServletResponse response, RedirectAttributes attr, ModelMap map) {
        System.out.println(attr.getFlashAttributes().get("test"));
        System.out.println("aaaaaaaaaaaaaa" + map.get("test"));
        HttpSession session = request.getSession();
        session.setAttribute("sessiontest","session test text...."+session.getId());
        String url = request.getScheme()+":111//"+request.getServerName()+":"+request.getServerPort()+"-"+request.getLocalPort()+"/"+request.getContextPath()+"/"+request.getRequestURI();
        session.setAttribute("ctpath",url);
        return "module1/page1";
    }

    @GetMapping("/page2")
    public String page2(HttpServletRequest request, HttpServletResponse response, RedirectAttributes attr) {
        attr.addFlashAttribute("test", "testaaaaa");
        return "redirect:/module1/page1";
    }

}

page1.html

<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>Spring MVC + Thymeleaf Example</title>
</head>
<body>
<!-- Project ContextPath -->
<input type="hidden" id="ctx" th:value="${application.ctx}"/> Hello,
<br/> ContextPath,
<span th:text="${session.ctpath}"/>!
<br/> Hello,
<span th:text="${test}"/>!
<br/> session,
<span th:text="${session.sessiontest}"/>!
<form th:action="@{/submit}">
    <input type="text" name="name"/>
    <button type="submit">submit</button>
</form>
</body>
</html>

未做session共享之前的结果

未做session共享之前的结果

session共享

项目结构

整体项目结构与原来保持一致

pom.xml

原pom.xml中加入
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.3.8.RELEASE</version>
            <!-- 用了springboot2 可能还没有更新,需要显示加入版本号,否则不用 -->
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

application.yml

将原来的application.properties改名了

加入:

spring:
  redis:
    database: 0
    host: ***
    port: 6379
    password: ***
    timeout: 0
    pool:
      max-active: 8
      max-wait: -1
      max-idle: 8
      min-idle: 0
    session:
      store-type: none

配置文件

加入新文件RedisHttpSessionConfig.java

package com.xiang.springboot.demo.module1.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
//maxInactiveIntervalInSeconds 默认是1800秒过期,这里测试修改为60秒
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=60)
public class RedisHttpSessionConfig{

}

其他不用变

最终结果

最终结果

代码地址:
https://gitee.com/soft_xiang/...

---------------2018.06.20 更新-----------------------------------------------

使用spring session之后原httpsessionListener的创建和销毁session的监听器会失效
处理方法:https://docs.spring.io/spring...

代码如下:

@Configuration
//maxInactiveIntervalInSeconds 默认是1800秒过期,这里测试修改为60秒
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=180)
public class RedisHttpSessionConfig{

    @Bean
    public SessionEventHttpSessionListenerAdapter getSessionEventHttpSessionListenerAdapter(){
        List<HttpSessionListener> listeners = new ArrayList<>();
        listeners.add(getHttpSessionListener());
        return new SessionEventHttpSessionListenerAdapter(listeners);
    }

    @Bean
    public HttpSessionListener getHttpSessionListener(){
        return new MyHttpSessionListener();
    }
}

---------------2018.06.20 更新end-----------------------------------------------

参考:

不是springboot实现方式,但讲的较好,推荐
https://www.cnblogs.com/youzh...

springboot方式,有一些踩坑记录
https://blog.csdn.net/dream_b...


soft_xiang
38 声望5 粉丝