Spring Session JDBC的使用 - javadevjournal


在本文中,我们将看到如何将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实现。