在本文中,我们将看到如何将Spring Session与JDBC一起使用。Spring Session提供了一种透明的方法来解决HTTP会话的限制。它提供了中央会话管理,而不必依赖于特定于容器或服务器的解决方案(例如Tomcat,Jetty等)。它提供了不同的选项来存储和管理会话信息。在本文中,我们将逐步完成将JDBC与Spring Session集成的步骤。
如果您使用的是Spring Boot,则需要在应用程序的pom.xml文件中添加以下依赖项:
<dependencies> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-jdbc</artifactId> </dependency> <!-- Adding this to have datasource and other feature available to us --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
我们不需要为Spring会话添加依赖项,因为Spring Boot会自动激活的。基于以上配置,Spring Boot自动配置将为我们处理其余配置。作为最后一步,我们需要通知Spring Boot使用jdbc来存储会话信息。在application.properties文件中添加以下属性:
spring.session.store-type=jdbc # Session store type.
|
如果仅使用单个会话模块,则可以从application.properties文件中省略上述属性。Spring Boot自动使用默认jdbc存储实现。如果有一个以上的实现,则必须指定上述属性。
在使用JDBC支持的spring会话之前,我们需要在应用程序中添加一些属性。属性文件:
spring.datasource.url=jdbc:mysql://localhost:3306/spring-session-jdbc spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
为了使Spring会话能够使用我们的JDBC配置,它需要在数据库中创建一个特定的表,我们可以在以下属性的帮助下启用此功能:
spring.session.jdbc.initialize-schema=always
|
启用这些属性后,如果我们指定spring.session.jdbc.initialize-schema=never,则需要手动创建会话表。Spring会话JDBC jar包含用于创建所需架构的SQL脚本。您可以在org.springframework.session.jdbc软件包中发现并检查jar包。
这是MySQL数据库的表结构:
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;
|
如果您使用 @EnableJdbcHttpSession,则上述数据表配置将不起作用。这意味着我们正在显式配置Spring Session,因此Spring Boot不会自动创建这个表。为了处理这个用例,我们有以下两种选择。
- 不要使用 @EnableJdbcHttpSessionSpring Boot,通过自动配置来处理它。
- 如果继续使用@EnableJdbcHttpSession注释,请手动创建表结构。
让我们创建一个简单的REST控制器来查看实际的会话处理:@RestController public class GreetingController {
@GetMapping("/") public @ResponseBody ResponseEntity<List> getMessage(Model model, HttpSession session) { List greetings = (List) session.getAttribute("GREETING_MESSAGES"); if(greetings == null) { greetings = new ArrayList<>(); }
return new ResponseEntity<List>(greetings,HttpStatus.OK); }
@PostMapping("/messages") public @ResponseBody ResponseEntity<List> saveMessage(@RequestParam("message") String greeting, HttpServletRequest request) { List greetings = (List) request.getSession().getAttribute("GREETING_MESSAGES"); if(greetings == null) { greetings = new ArrayList<>(); request.getSession().setAttribute("GREETING_MESSAGES", greetings); } greetings.add(greeting); return new ResponseEntity<List>(greetings,HttpStatus.OK); } }
|
主类:
@SpringBootApplication @EnableJdbcHttpSession public class SpringSessionWithJdbcApplication {
public static void main(String[] args) { SpringApplication.run(SpringSessionWithJdbcApplication.class, args); } }
|
唯一有趣的一点是@EnableJdbcHttpSession注释。如果我们运行应用程序并访问端点。具有JDBC配置的Spring Session将透明地处理会话管理。Spring会话透明地处理这个问题。@EnableJdbcHttpSession注释创建了一个Spring Bean,其名称springSessionRepositoryFilter实现了Filter。该过滤器负责替换由Spring Session支持的HttpSession实现。