実はいろいろと情報が錯綜していたため、動作するまでに一手間がかかりました(´・ω・)
目的
SpringBoot2+SpringSessionを利用してセッション情報をデータベースで管理する
動作環境+バージョン情報
以下で動作確認をしています。
- SpringBoot 2.0.5.RELEASE。
- Oracle XE
- SpringBoot-starter
- web
- session-core
- session-jdbc
- HikariCP
SpringSessionJdbcに必要なライブラリ依存関係は、Appendixのmaven(pom.xml)に記載しております。バージョンを略記しているものは、SpringBoot2.0.5管理下にあるものを使います。
下準備
SpringSessionでデータベース利用に必要なもの
maven(pom.xml)のとおり、最低限以下が必要です。
- spring-boot-starter
- web
- session-core
- session-jdbc
- 接続プール (今回はSpringBoot2から推奨されている HikariCP を利用しています)
- 設定ファイルにデータベース接続プールの設定と、SpringSessionの設定を記載
利用するためのConfigクラス
@EnableJdbcHttpSession
を宣言します。SpringBootでアプリケーションを作るときはよくConfigureクラスなどで作ります。もしアプリケーション内でJDBCの設定がない場合は、JDBCのトランザクション設定を書きます。以下はJavaConfigの例。
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.session.jdbc.config.annotation.web.http.EnableJdbcHttpSession;
import org.springframework.transaction.PlatformTransactionManager;
/**
* @author A-pZ
*/
@EnableJdbcHttpSession
public class JdbcHttpSessionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
JDBC設定
JDBCの設定は、Appendixの設定(application.yml) を参考にしてください。
HTTPセッションを利用するController
では具体的に、HttpSessionを利用するControllerです。
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author A-pZ
*/
@Controller
public class SampleController {
@GetMapping("")
public String start(HttpSession session) {
session.setAttribute("sample", "sample");
return "index";
}
}
このController実行後の画面(index.html)は、特に何もしない静的HTMLのThymeleafテンプレートを出力させます(JSPでも良いでしょう)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
</head>
<body>
index.html
</body>
</html>
動作後、セッションを扱っているデータベースのレコードを見ると、
このようにセッション情報がデータベースに格納されていることがわかります。
Appendix
maven(pom.xml)
Oracle JDBCドライバは別途ローカルリポジトリか、ローカル環境のNexusなどのリポジトリへ登録してください。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.alphapz.springsample</groupId>
<artifactId>spring-session-sample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-session-sample</name>
<description>spring-session-sample</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.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>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>oracle.jdbc</groupId>
<artifactId>ojdbc7</artifactId>
<version>12.1.0.2.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
設定(application.yml)
SpringSessionJdbcを動作させるための最低限の設定です。
spring:
session:
timeout: 300
jdbc:
initialize-schema: always
table-name: SPRING_SESSION
datasource:
url: jdbc:oracle:thin:@127.0.0.1:1521:xe
username: springsession
password: springsession
tomcat:
data-source: com.zaxxer.hikari.HikariDataSource
投入SQL(Oracle DB)
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME NUMBER(19,0) NOT NULL,
LAST_ACCESS_TIME NUMBER(19,0) NOT NULL,
MAX_INACTIVE_INTERVAL NUMBER(10,0) NOT NULL,
EXPIRY_TIME NUMBER(19,0) NOT NULL,
PRINCIPAL_NAME VARCHAR2(100 CHAR),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);
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 VARCHAR2(200 CHAR) 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
);
ハマリポイント
JDBCを利用したSpringSessionを有効化するためには、実はかなり設定する箇所が減っており、@EnableJdbcHttpSession
で必要なSpringBean定義は、TransactionManager から DataSource を渡すだけで済みます。
実はこのDataSource設定を何らかのJavaConfigで記載したときには、Beanの優先度をつけるか、Qualifierで別名をつけないと、起動時エラーになります。なお、旧来のSpringBootで利用しているDataSource設定の記述をすると、DataSourceの設定方法が変わったため、これまた実行時エラーになります。(データソースの型が解決できない、または、ymlから読み込んだが型に変換できない、など…)