SpringSession的使⽤⽰例
⽬录
Session
Session常⽤解决⽅案
Spring-Session
测试代码
基于数据库的Spring-Session
基于Redis的Spring-Session
总结
Session
Http协议是⽆状态的,这样对于服务端来说,没有办法区分是新的访客还是旧的访客。但是,有些业务场景,需要追踪⽤户多个请求,此时就需要Session。关于session的百度百科session
Session:在计算机中,尤其是在⽹络应⽤中,称为“会话控制”。Session对象存储特定⽤户会话所需的属性及配置信息。这样,当⽤户在应⽤程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,⽽是在整个⽤户会话中⼀直存在下去。当⽤户请求来⾃应⽤程序的 Web页时,如果该⽤户还没有会话,则Web服务器将⾃动创建⼀个 Session对象。当会话过期或被放弃后,服务器将终⽌该会话
核⼼特点:
1. 服务端存储
2. 会过期
Session常⽤解决⽅案
对于Session的常⽤解决⽅案,可以划分为三种。
负载均衡⽅式
借助负载均衡设备或者模块,将指定的Session始终路由到同⼀台机器即可,如Nginx。
副本复制⽅式
利⽤服务器节点间的副本复制⽅式,保证集所有节点拥有的Session数据⼀致。
集中存储⽅式
引⼊第三⽅存储,将Session数据集中存储到外部存储中,如Redis或者数据库等。
本⽂介绍的Spring-Session是采⽤第三种,集中存储的⽅式。
Spring-Session
核⼼组成模块
Spring Session Core
提供Spring Session核⼼的功能和API
Spring Session Data Redis
提供基于Redis的SessionRepository以及配置
Spring Session JDBC
提供基于关系型数据库的SessionRepository以及配置
Spring Session Hazelcast
提供基于Hazelcast的SessionRepository以及配置
测试代码
controller提供三个接⼝,分别对应Session的获取、保存和清理
@GetMapping("/")
public String process(Model model, HttpSession session) {
@SuppressWarnings("unchecked")
List<String> messages = (List<String>) Attribute("springSession");
if (messages == null) {
messages = new ArrayList<>();
}
model.addAttribute("sessionMessages", messages);
return "sessionTest";
}
@PostMapping("/persistSession")
public String persistMessage(@RequestParam("msg") String msg, HttpServletRequest request) {
@SuppressWarnings("unchecked")
List<String> messages = (List<String>) Session().getAttribute("springSession");
if (messages == null) {
messages = new ArrayList<>();
}
messages.add(msg);
return "redirect:/";
}
@PostMapping("/destroySession")
public String destroySession(HttpServletRequest request) {
return "redirect:/";
}
sessionTest.html对应页⾯操作
<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head>
<meta charset="UTF-8">
<title>Spring Boot Session Example</title>
</head>
<body>
<div>
<form th:action="@{/persistSession}" method="post">
<textarea name="msg" cols="40" rows="2"></textarea>
<br> <input type="submit" value="保存" />
</form>
</div>
<div>
<h2>session列表</h2>
<ul th:each="message : ${sessionMessages}">
<li th:text="${message}">message</li>
</ul>
</div>
<div>
<form th:action="@{/destroySession}" method="post">
<input type="submit" value="清空" />
</form>
</div>
</body>
</html>
基于数据库的Spring-Session
1.引⼊maven依赖
使⽤MySQL存储,所以引⼊了MySQL。
涉及到SpringBoot JDBC的配置,引⼊了Spring Boot JDBC Starter。
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
注意:
No session repository could be auto-configured, check your configuration (session store type is 'jdbc')如果存在这个报错,是因为没有引⼊spring-boot-starter-jdbc,引⼊即可。
2.配置application.properties⽂件
主要包含两部分,数据库的配置以及Spring Session Jdbc配置。
# 配置数据源相关内容
spring.datasource.sql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/spring_learn?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=xxx
spring.datasource.password=xxx
spring.datasource.initialization-mode=always
# session类型选择jdbc
spring.session.store-type=jdbc
spring.session.jdbc.initialize-schema=always
# 指定表名
#spring.session.jdbc.table-name=SESSIONS
# 超时时间
spring.session.timeout=180s
3.数据库存储解析
默认情况下,数据库中会创建2张表。SPRING_SESSION和SPRING_SESSION_ATTRIBUTION。
SPRING_SESSION⽤于存在session⾃⾝的⼀些属性,如创建时间、过期时间等,详细schema如下。
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) DEFAULT NULL,
PRIMARY KEY (`PRIMARY_ID`),
UNIQUE KEY `SPRING_SESSION_IX1` (`SESSION_ID`),
KEY `SPRING_SESSION_IX2` (`EXPIRY_TIME`),
KEY `SPRING_SESSION_IX3` (`PRINCIPAL_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
SPRING_SESSION_ATTRIBUTION⽤于存储session相关联的属性,schema如下。
CREATE TABLE `SPRING_SESSION_ATTRIBUTES` (
`SESSION_PRIMARY_ID` char(36) NOT NULL,
`ATTRIBUTE_NAME` varchar(200) NOT NULL,
`ATTRIBUTE_BYTES` blob NOT NULL,
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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC
4.测试执⾏
SPRING_SESSION中的数据
SPRING_SESSION_ATTRIBUTION中的数据。
基于Redis的Spring-Session
⼏乎同样的步骤
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
application.properties配置
spring.session.store-type=redis
结果分析
⼀次请求后,多了三个属性,分析如下。
key类型⽤途value
spring:session:sessions:expires:${sessionId}string判断sesssion是否存在空
spring:session:sessions:${sessionId}hash session相关的属性,包括有效
creationTime/lastAccessedTime/sessionAttr/maxInactiveInterval
期、创建时间、具体属性等spring:session:expirations:1623656160000set存储待过期的sessionId列表key: 过期的时间戳;value: 在这个时间戳将要过期的expire key 列表。
key类型⽤途value
在访问时,先通过第⼀个key,判断session是否存在以及是否过期。如果没有过期,可以通过第⼆个key获取或者更新对应的session详情。
订阅Spring-Session的相关事件
spring framework和spring的关系有些时候,我们⽐较关⼼Session的创建或者销毁事件,做⼀些特殊的处理或者记录。基于Redis的Spring-Session利⽤Spring Event将该事件发布出来,我们可以使⽤EventListener监听做处理。
@Component
@Slf4j
public class AnnotationDrivenEventListener {
@EventListener
public void handleSessionCreated(SessionCreatedEvent sessionCreatedEvent) {
String sessionId = SessionId();
log.info("session id:{} created", sessionId);
}
@EventListener
public void handleSessionDestroyed(SessionDestroyedEvent sessionDestroyedEvent) {
String sessionId = SessionId();
log.info("session id:{} destroyed", sessionId);
}
}
总结
Spring Session提供了⾮常便利的,基于关系型数据库或者Redis的Session解决⽅案。
Redis版访问速度快,基于Redis的过期策略,保证过期数据会被删除,同时⽀持事件订阅。
数据库版直接基于数据库,⽆需单独引⼊其他存储。但是访问速度相对较慢,过期数据需要依赖应⽤程序⾃⾝进⾏删除。同时没有提供事件订阅能⼒。
以上就是Spring Session的使⽤⽰例的详细内容,更多关于Spring Session的使⽤的资料请关注其它相关⽂章!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论