Java
spring
spring-session

Spring-Sessionを使ってみた

More than 3 years have passed since last update.

Tomcatセッションを外部ストレージに置き換える場合にどうしてもTomcat側で難しい設定をしたり、ライブラリを配置したりで億劫になることが多かった。

pom.xmlにdependencyを追加したら置き換わるくらいの簡単なもので、且つセッションストレージがRedisとなるものを探していた。

そんなところにSpringのリリースブログで今月初めにこんな記事を見つけた。

Spring Session 1.0.0.RELEASE


TODO (2015/04/14追記)

あとでまとめる


Spring-Sessionを使ってみての結論

先に結論言っちゃいます。

以下、問題なければ使えます。


Sessionの張り替え

できません。

session.invalidate();

session.getSession(true);

って同じリクエスト内でやっても生成されたJSESSIONIDはCookieに設定されなかった。

破棄されたJSESSIONIDが次のリクエストで設定されてたからセッションエラーになる。


SessionAttributeの書き換え


request1

User user = (User) session.getAttribute("sessionUser");

System.out.println(user.getName()); // John
user.setName("Emily");


request2

User user = (User) session.getAttribute("sessionUser");

System.out.println(user.getName()); // John

TomcatデフォルトのHttpSession実装はEmilyになる。


Spring Sessionとは

こんなことができるらしい。



  • API and implementations (i.e. Redis) for managing a user’s session

  • HttpSession - allows replacing the HttpSession in an application container (i.e. Tomcat) neutral way. Additional features include:

  • Clustered Sessions - Spring Session makes it trivial to support clustered sessions without being tied to an application container specific solution.

  • Multiple Browser Sessions - Spring Session supports managing multiple users’ sessions in a single browser instance (i.e. multiple authenticated accounts similar to Google).

  • RESTful APIs - Spring Session allows providing session ids in headers to work with RESTful APIs

  • WebSocket - provides the ability to keep the HttpSession alive when receiving WebSocket messages


日本語訳だとこうなる。(適当に翻訳したので悪しからず。内容は間違ってないはず。)


  • ユーザーセッションを管理するAPIとその実装(例えばRedis)を提供する。

  • HttpSession - アプリケーションコンテナ(例えばTomcat)のHttpSessionに仲介する形でその機能を置き換える。さらに追加する機能は次の通り。

  • クラスターセッション - アプリケーションコンテナ固有の問題に縛られることなく、クラスタリングされたセッションをサポートすることができる。

  • 複数セッション - 1つのブラウザで複数のユーザーセッションを管理することができる。(例えばGoogleのような複数の認証アカウントが存在する場合がこれにあたる。)

  • RESTful API - RESTfulなAPIでも動作するようにセッションIDをHTTPヘッダで提供できる

  • WebSocket - WebSocketでメッセージを受け取ったときもHttpSessionを有効にし続ける機能を提供する

らしい。1つめと2つめの内容で試してみたいと思った。


既存のWebアプリケーションに導入

Springを利用している既存のWebアプリケーションに入れてみた。


pom.xml

<dependency>

<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>


web.xml

<filter>

<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


RedisConfig.java

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 180) // 3分

public class RedisHttpSessionConfig {

// XMLで定義済みで他目的のRedisConnectionFactoryと
// 接続先を分けるときの対応として名前付きでInjectする
@Resource(name = "session.redisConnectionFactory")
private RedisConnectionFactory redisConnectionFactory;

@Bean
public RedisConnectionFactory connectionFactory() {
return redisConnectionFactory;
}

// セッションIDをCookieで管理する設定
@Bean
public CookieHttpSessionStrategy httpSessionStrategy() {
CookieHttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();
httpSessionStrategy.setCookieName("JSESSIONID");

return httpSessionStrategy;
}
}


RedisHttpSessionConfig.javaは自前で用意。コンポーネントスキャン対象のパッケージ以下に配置しておく。

Springの設定ファイルをXMLで管理していたけど@EnableRedisHttpSessionが色々やってくれるからここだけは大人しくJavaConfigにしておく。

余談だけどこういう書き方もできる。

  // @Resource(name = "session.redisConnectionFactory")

// private RedisConnectionFactory redisConnectionFactory;

@Bean
public RedisConnectionFactory connectionFactory(@Qualifier("session.redisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
return redisConnectionFactory;
}

設定終わり。これだけでSession管理がアプリケーションコンテナからSpring-SessionのRedis実装に置き換わった。