如何將Spring Session與JDBC結合使用? | Java Development Journal

banq發表於2019-07-08

在本文中,我們將瞭解如何將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支援的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配置,它需要在DB中建立某個表,我們可以通過以下屬性啟用此功能:

spring.session.jdbc.initialize-schema=always

一旦我們啟用這些屬性如果我們指定spring.session.jdbc.initialize-schema=never,那麼我們需要手動建立會話表。Spring會話JDBC jar包含用於建立所需模式的SQL指令碼。您可以在org.springframework.session.jdbc包下看到。

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;

Spring JDBC Session和@EnableJdbcHttpSession

如果您使用  @EnableJdbcHttpSession,以上配置將無法正常工作。spring.session.*不適合你的原因是因為你正在使用@EnableJdbcHttpSession。

這意味著我們正在明確自己來配置Spring Session,因此Spring Boot的自動配置會不起作用。為了處理這個情況,我們有以下兩個選項:

  1. 不要用 @EnableJdbcHttpSession,讓Spring Boot通過自動配置來處理它。
  2. 如果繼續使用@EnableJdbcHttpSession註釋,請手動建立架構  。

REST控制器

讓我們建立一個簡單的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);
    }
}

Spring Boot主類:

@SpringBootApplication
@EnableJdbcHttpSession
public class SpringSessionWithJdbcApplication {

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

@EnableJdbcHttpSession註釋建立一個名為的Spring bean springSessionRepositoryFilter實現Filter。過濾器負責替換由Spring Session支援的HttpSession實現。

 

相關文章