前言

网上的例子大部分是使用redis解决session共享问题,其实spring还提供了其他方案:

Spring Session Core - provides core Spring Session functionalities and APIs

Spring Session Data Redis - provides SessionRepository and ReactiveSessionRepository implementation backed by Redis and configuration support

Spring Session JDBC - provides SessionRepository implementation backed by a relational database and configuration support

Spring Session Hazelcast - provides SessionRepository implementation backed by Hazelcast and configuration support

接下来讲使用mysql的方式

创建数据库

DROP TABLE IF EXISTS SPRING_SESSION_ATTRIBUTES;
DROP TABLE IF EXISTS SPRING_SESSION;
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) ENGINE=INNODB ROW_FORMAT=DYNAMIC;

CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);

CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) ENGINE=INNODB ROW_FORMAT=DYNAMIC;

这里创建了两个表,一个保存session一个保存session绑定的属性。该表结构是spring-session-jdbc指定的,不要修改结构

引入依赖

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

当引入了spring-session-jdbc后会自动包含spring-session-core

配置session

spring:
datasource:
#连接信息
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
session:
#session超时时间
timeout: 120s
jdbc:
#清理session计划任务,默认是每分钟一次
cleanup-cron: 0 * * * * *

当依赖中只有一个spring-session-jdbc时,不需要再指定spring.session.store-type=JDBC。
只有当存在多个实现(spring-session-redis)时才需要指定

使用

@RestController
public class IndexController {
@RequestMapping(name = "/login", method = RequestMethod.POST)
public String login(HttpSession session, String username, String pwd) {
if (StringUtils.isBlank(username) || StringUtils.isBlank(pwd)) {
return "username和pwd不能为空";
}
session.setAttribute("username", username);
session.setAttribute("logintime",LocalDateTime.now());
return username + "登陆成功";
}


@RequestMapping(name = "/", method = RequestMethod.GET)
public String index(HttpSession session) {
String username = (String) session.getAttribute("username");
if (StringUtils.isBlank(username)) {
return "您还未登录!";
} else {
return "欢迎您" + username + ",登陆时间为" + session.getAttribute("logintime");
}

}
}

首先访问localhost:8080/login登陆,可以看到数据库中的记录

SPRING_SESSION表

SPRING_SESSION
SPRING_SESSION

SPRING_SESSION_ATTRIBUTES表

SPRING_SESSION_ATTRIBUTES
SPRING_SESSION_ATTRIBUTES

至此,实现完成

参考

  1. spring-session
  2. httpsession-jdbc-boot