Spring Boot 2系にてRedis(on Docker)を使ってセッション管理する


Spring Boot 2系とSpring Session Redisを使ってセッション管理を実装してみたが、 調べた内容では上手く動作しなかった(というかRedisの方がライブラリのバージョンアップに伴い、Duprecated となっていたメソッドがあり実装を変える必要があった)ので備忘として残しておく。

環境とかバージョンとか

  • windows 8.1
  • Docker Toolbox for win
  • Spring Boot 2.0.4.RELEASE

実装

application.properties

spring.session.store-type=redis
spring.session.redis.flush-mode=on-save # Sessions flush mode.
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.

application.propertiesはこんな感じ。ここは特別なことは特にない。

pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

pomはこんな感じ。ってきり、上2つだけ宣言すればよいと思っていただが、jediscommons-pool2も定義しておかないとNoClassDefErrorが出てしまうので注意。

Configクラス

package com.example.ek.session;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration
@EnableRedisHttpSession
public class SpringSessionConfig {

    @Bean
    public JedisConnectionFactory connectionFactory() {
          RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
          redisStandaloneConfiguration.setHostName("192.168.99.100");
          redisStandaloneConfiguration.setPort(6379);
          return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

}

ポイントはこのクラスで、色々調べると元々はJedisConnectionFactoryクラスにsetHostName, setPort等のメソッドがあって、そこに設定を追加してreturnすれば良かったようなのですが、2.0以上は Deprecated になってしまっていてEclipseに怒られる。で、javadoc見ると『 RedisStandaloneConfiguration を使え』と記載があったので、 JedisConnectionFactoryのコンストラクタに引数として渡してreturnする。

package com.example.ek.session;

import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;

public class HttpSessionApplicationInitializer extends AbstractHttpSessionApplicationInitializer {

    public HttpSessionApplicationInitializer() {
        super(SpringSessionConfig.class); 
    }
}

ここは特に珍しいことはない。コンストラクタでスーパークラス呼び出して引数にconfigクラスをセットする。

Docker

一応Dockerでやったことも記載しておく。

$ docker-machine env --shell default
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH=**
export DOCKER_MACHINE_NAME="default"
export DOCKER_COVERT_WINDOWS_PATHS="true"

こんな感じで出てくる項目をexportコマンドで1つ1つ設定していく。

$ export DOCKER_TLS_VERIFY="1" 

あとはdocker runするだけ。

$ docker container run --name sample-redis -d -p 6379:6379 redis

// omitted

$ docker container ls
CONTAINER ID     IMAGE      COMMAND    CREATED      STATUS       PORTS      NAMES
ce9e74e42aa9      redis      "docker-entrypoint.s"      8 seconds ago      Up 7 seconds      0.0.0.0:6379->6379/tcp      sample-redis

これで準備OKなので、redisにコンソールで入り、redis-cliと打つ

$ docker exec -it redis bash
root@ce9e74e42aa9:/data# redis-cli
127.0.0.0:6379>

keys *コマンドを打つとRedisに記録されているセッション情報が表示される。最初はモチロン空だが、アプリを起動→ログインすると、無事Redisにセッションが記録されていることがわかる。

127.0.0.0:6379> keys *
1) "spring:session:sessions:expires:**********"
2) "spring:session:sessions:********"
3) "spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:********"

実際のソースコードは以下に載せています。
ソースコード