Spring Sessionとは
HttpSessionの機能を上書きして、RedisやRDBMSなどでセッション情報を管理することができます。
通常はアプリケーションサーバでセッション情報を管理していますが、複数台のサーバを用意してロードバランスしながら運用している場合、複数サーバ間でセッション情報を同期する(セッションレプリケーション)、もしくはユーザとサーバが1対1となるようにロードバランスする(スティッキーセッション)といった必要があり、何かと面倒です。
そこで、セッション情報をアプリケーションサーバ以外の場所に切り出してしまおう、というときにSpring Sessionはいい感じに使えます。
Spring Sessionを使う
プロジェクトの作成
Spring InitializrでSpring Bootプロジェクトを作成します。
https://start.spring.io/
今回はDependenciesとして以下を追加しました。
- Web
- Thymeleaf
- Session
- JDBC
- PostgreSQL
- Lombok
セッション情報を格納するRDBMSはPostgreSQLにしています。
application.properties
spring.session.store-type=jdbc
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.session.store-typeをjdbcにしておけば、SpringSession関連の設定が勝手に行われる感じです。
いやーSpringBootって便利ですね。
(datasourceの設定は環境に合わせて指定してください。)
データベースのセットアップ
自動的にセットアップする方法もありそうな気がしますが、やり方がよくわからないので、セッション情報を格納するためのテーブルを作成します。
SpringSessionJdbc内にsqlファイルが存在するのでそれを実行すればOKです。
https://github.com/spring-projects/spring-session/tree/master/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc
※上記はGitHubのmasterなので、バージョンによってはSQLが異なる可能性があります。
セッションを操作してみる
以下のようなControllerクラスを作成してセッション情報を操作してみました。
@Controller
public class HelloController {
@Autowired
SessionData sessionData;
@GetMapping(value = "/")
public String index() {
return "index";
}
@GetMapping(value="/set")
public String set(){
sessionData.setStr1("hogehoge");
sessionData.setStr2("fugafuga");
sessionData.setStr3("piyopiyo");
return "redirect:/";
}
}
@Data
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class SessionData implements Serializable{
private static final long serialVersionUID = 1L;
String str1;
String str2;
String str3;
}
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Hello Thymeleaf</title>
</head>
<body>
<div>
str1:
<span th:text="${@sessionData.str1}">aaa</span>
</div>
<div>
str2:
<span th:text="${@sessionData.str2}">aaa</span>
</div>
<div>
str3:
<span th:text="${@sessionData.str3}">aaa</span>
</div>
<form th:action="@{/set}" method="get">
<button>set</button>
</form>
</body>
</html>
実装についてはいつも通りセッションを操作すればOKです。
データベースを確認すると、そこにセッション情報が保持されていることがわかります。
なお、データはSerializeして格納するため、セッション情報はSerializableを実装する必要があります。
以上のように、簡単にセッション情報をRDBMSに格納することが出来ます。
個人的には情報をJSONにして格納してしてくれたほうが色々取り回しやすいかなーと思いました。
データ変換部分をカスタマイズできるらしいのですが、データ型を変更するとなると大変そうなので諦めました。
(DBのスキーマも変わるので、ほぼ作り変えないといけない。)
なお、Redisを利用する実装にはJSONでデータを格納する方法が提供されているようです。