关于session共享的方式有多种:

(1)通过nginx的ip_hash,根据ip将请求分配到对应的服务器

(2)基于关系型数据库存储

(3)基于cookie存储

(4)服务器内置的session复制域。

(5)基于nosql(memcache、redis都可以)

(6) 使用spring session ,其实也是借助于redis实现。

常用的就是6和5,下面研究第5和6种方式。

多示例的情况下session 一致性问题:

实现方式6,使用spring session 实现:

1. pom.xml实现依赖如下:

<properties>
<weixin-java-mp.version>2.8.0</weixin-java-mp.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.locales>zh_CN</project.build.locales>
</properties>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> </exclusion> </exclusions> -->
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- Testing Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>

</dependencies>

2.YML配置信息

server:
port: 8081
spring:
redis:
database: 0
host: 106.13.99.25
port: 6379
password: root
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 8
min-idle: 0
timeout: 10000
redis:
hostname: 106.13.99.25
port: 6379
password: root

3.创建SessionConfig

package com.hou.session;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

//这个类用配置redis服务器的连接
//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {

// 冒号后的值为没有配置文件时,制动装载的默认值
@Value("${redis.hostname:localhost}")
String HostName;
@Value("${redis.port:6379}")
int Port;
@Value("${redis.password}")
String password;

@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(Port);
connection.setHostName(HostName);
connection.setPassword(password);
return connection;
}
}

4.初始化Session

package com.hou.session;

import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;

//初始化Session配置
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer {
public SessionInitializer() {
super(SessionConfig.class);
}
}

5. controller 类实现

/**
*/
package com.hou.controller;

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

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
*/
@SpringBootApplication
@RestController
public class SessionController {
@Value("${server.port}")
private String serverPort;

@RequestMapping("/")
public String index() {
return serverPort;
}

// 创建session 会话
@RequestMapping("/createSession")
public String createSession(HttpServletRequest request, String nameValue) {
// 默认 创建一个session,
HttpSession session = request.getSession();
System.out.println(
"存入Session sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);
session.setAttribute("name", nameValue);
return "success-" + serverPort;
}

// 获取session 会话
@RequestMapping("/getSession")
public Object getSession(HttpServletRequest request) {
// 设置为true 情况下的时候,客户端使用对应的sessionid 查询不到对应的sesison 会直接创建一个新的session
// 设置为false 情况下的时候,客户端使用对应的sessionid 查询不到对应的sesison 不 会直接创建一个新的session
HttpSession session = request.getSession(false);
if (session == null) {
return serverPort + " 该服务器上没有存放对应的session值";
}
System.out.println("获取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);
Object value = session.getAttribute("name");
return serverPort + "-" + value;
}

}

实现方式5,使用redis 实现:

基于令牌(Token)方式实现Session解决方案,因为Session本身就是分布式共享连接

@Service
publicclass TokenService {
@Autowired
private RedisService redisService;

// 新增 返回token
public String put(Object object) {
String token = getToken();
redisService.setString(token, object);
returntoken;
}

// 获取信息
public String get(String token) {
String reuslt = redisService.getString(token);
returnreuslt;
}

public String getToken() {
return UUID.randomUUID().toString();
}

}
@RestController
publicclass TokenController {
@Autowired
private TokenService tokenService;
@Value("${server.port}")
private String serverPort;

@RequestMapping("/put")
public String put(String nameValue) {
String token = tokenService.put(nameValue);
returntoken + "-" + serverPort;
}

@RequestMapping("/get")
public String get(String token) {
String value = tokenService.get(token);
returnvalue + "-" + serverPort;
}

}