Spring Session Management – Spring Session JDBC

时间:2020-02-23 14:36:02  来源:igfitidea点击:

Spring Session Module提供用于管理Web应用程序中用户会话的API和实现。

Spring会话

Spring Session由以下模块组成:

  • Spring Session Core:为会话管理提供API和核心支持。

  • Spring Session JDBC:使用关系数据库提供会话管理。

  • Spring Session Data Redis:为Redis数据库提供会话管理实现。

  • Spring Session Hazelcast:使用Hazelcast提供会话管理支持。

Spring会话的好处

  • Spring Session将会话管理逻辑与应用程序分离开来,从而使其更具容错能力。

  • Spring Session将用户会话信息保存在数据库中,因此,在具有多个服务器节点的集群环境中使用它非常有用。
    我们不需要粘性会话或者会话复制逻辑。

  • 如果应用程序崩溃,则用户会话数据不会丢失。
    再次启动应用程序时,它将获取所有用户会话数据。

  • 只需更改一些配置,我们就可以在会话存储软件之间进行切换,我们可以从使用Redis切换到JDBC。

  • Spring是一个开源项目,很容易引导。
    如果您遇到任何问题,很有可能会在网上轻松找到解决方案。

Spring Session JDBC示例

让我们创建一个简单的Spring Session JDBC示例项目。
我将在应用程序中使用Spring Boot和MySQL数据库。
因此,我们需要在项目中遵循以下依赖关系。

  • spring-boot-starter-web:这是一个Spring MVC Web应用程序。

  • spring-boot-starter-jdbc:用于Spring Boot JDBC支持和自动配置。

  • spring-boot-starter-thymeleaf:这是为了支持Thymeleaf用于我们的视图页面。
    Thymeleaf易于使用,并且与Spring框架集成良好。

  • spring-session-core:Spring Session Core API

  • spring-session-jdbc:Spring Session JDBC实现

  • mysql-connector-java:MySQL JDBC驱动程序Jar

这是我们最终的pom.xml文件:

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

	<groupId>com.theitroad.spring</groupId>
	<artifactId>Spring-Session-Example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>Spring-Session-Example</name>
	<description>Spring Session Example</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.3.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>10</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
	</dependencies>

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

您可以使用Spring Initializr生成基础Maven项目,然后添加所需的依赖项。

下图显示了Spring Tool Suite的最终项目结构。

让我们一一看一下每个组件。

application.properties

这是我们指定数据库配置和一些spring会话属性的地方。

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/SpringSessionDB
spring.datasource.username=theitroad
spring.datasource.password=theitroad

spring.session.store-type=jdbc
spring.session.jdbc.initialize-schema=always
spring.session.timeout.seconds=900

我将" spring.session.jdbc.initialize-schema"指定为" always",以便Spring为我们创建所需的表。

通常,在生产环境中,应用程序用户没有执行DDL语句的特权,在这种情况下,请将此属性设置为"从不",并根据JAR文件中提供的脚本手动创建数据库表。

index.html

这是我们使用Thymeleaf构建的视图页面。

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Spring Session JDBC Example</title>
</head>
<body>
	<div>
		<form th:action="@{/saveMessage}" method="post">
			<textarea name="msg" cols="40" rows="2"></textarea>
			<br> <input type="submit" value="Save Message" 
		</form>
	</div>
	<div>
		<h2>Messages</h2>
		<ul th:each="m : ${messages}">
			<li th:text="${m}">msg</li>
		</ul>
	</div>
	<div>
		<form th:action="@{/invalidate}" method="post">
			<input type="submit" value="Destroy Session" 
		</form>
	</div>
</body>
</html>

注意,/saveMessage将用于向服务器发送消息。
我们将把此消息保存到用户会话属性。

当请求主页时," messages"属性将被设置为model。
因此,如果用户会话有效,则应该在主页上看到所有已保存的消息。
Spring会话使用Cookies来标识用户会话,因此,如果您点击reload,那么您还将看到所有先前保存的消息。

最后,有一个按钮可以使会话无效并销毁会话。
会话销毁后,其属性将被删除,您将看不到之前保存的邮件。

HomeController.java

这是我们的控制器类,用于处理用户请求并将消息保存到用户会话属性。

package com.theitroad.spring;

import java.util.ArrayList;
import java.util.List;

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

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HomeController {

	@GetMapping("/")
	public String home(Model model, HttpSession session) {
		@SuppressWarnings("unchecked")
		List<String> msgs = (List<String>) session.getAttribute("MY_MESSAGES");

		if (msgs == null) {
			msgs = new ArrayList<>();
		}
		model.addAttribute("messages", msgs);

		return "index";
	}

	@PostMapping("/saveMessage")
	public String saveMessage(@RequestParam("msg") String msg, HttpServletRequest request) {
		@SuppressWarnings("unchecked")
		List<String> msgs = (List<String>) request.getSession().getAttribute("MY_MESSAGES");
		if (msgs == null) {
			msgs = new ArrayList<>();
			request.getSession().setAttribute("MY_MESSAGES", msgs);
		}
		msgs.add(msg);
		request.getSession().setAttribute("MY_MESSAGES", msgs);
		return "redirect:/";
	}

	@PostMapping("/invalidate")
	public String destroySession(HttpServletRequest request) {
		request.getSession().invalidate();
		return "redirect:/";
	}
}

大多数逻辑很简单,请注意我们没有使用Spring Session模块中的任何东西。
这是spring框架的优点,它将自动配置我们的应用程序以使用数据库进行会话管理。

SpringSessionExampleApplication.java

只是一个Spring Boot应用程序来运行我们的应用程序。

package com.theitroad.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringSessionExampleApplication {

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

Spring Session JDBC测试

我们的应用程序已经准备就绪,只需将SpringSessionExampleApplication类作为Java应用程序运行即可。
您会在控制台日志中注意到以下映射。

Mapped "{[/saveMessage],methods=[POST]}" onto public java.lang.String com.theitroad.spring.HomeController.saveMessage(java.lang.String,javax.servlet.http.HttpServletRequest)
Mapped "{[/invalidate],methods=[POST]}" onto public java.lang.String com.theitroad.spring.HomeController.destroySession(javax.servlet.http.HttpServletRequest)
Mapped "{[/],methods=[GET]}" onto public java.lang.String com.theitroad.spring.HomeController.home(org.springframework.ui.Model,javax.servlet.http.HttpSession)

您还将注意到记录器执行SQL脚本以创建数据库表。

Executing SQL script from class path resource [org/springframework/session/jdbc/schema-mysql.sql]

您也可以在数据库中检查这些表。

如日志所示,我们的index.html页面将被自动配置为欢迎页面。

2016-06-27 12:50:09.761  INFO 1666 --- [main] o.s.b.a.w.s.WelcomePageHandlerMapping: Adding welcome page template: index