前回は、CP型データベースである「Amazon ElastiCache」の概要を説明し、シングルノードでローカル環境へテーブル構築しました。続く今回は、構築したデータベースに「Spring Session」と「Spring Data Redis」を使ってアクセスするアプリケーションを実装してみます。

Spring Data SessionとSpring Data Redisの概要

Spring SessionはSpringのトップレベルプロジェクトの1つで、ユーザーのセッション情報に関するAPIとその実装を提供します。具体的には、以下のセッション情報を透過的に(従来のセッション情報と変わらないやり方で)扱うことが可能です。

  • HttpSession:従来アプリケーションサーバで保持していたセッション情報を共有キャッシュへ置き換える実装を提供します。
  • WebSockets:従来のスティッキーセッションセッションが必要なくなり、WebSocketsメッセージを取り扱うことが可能になります。
  • WebSession:Spring5からサポートされたノンブロッキングなWebSessionを取り扱うことが可能になります。

また、Spring Data Redisは、Spring Data JPAやこれまで紹介してきたSpring Data DynamoDBと同じくSpring Dataのメインモジュールで、統一的なインタフェースでデータアクセスを行えます。Spring Data Redisの特徴は、以下の通りです。

  • Jedisとlettuceなど、複数のRedisドライバを通した抽象的なアクセス手段の提供
  • CrudRepositoryの継承インタフェースによる基本的なデータアクセスコード実装量の軽減
  • @EnableRedisRepsitoriesアノテーションを使ったRepositoryインタフェースの拡張実装の提供
  • Redis driverがスローする例外の、共通的なDataAccessExceptionなどへの透過的な変換
  • Spring Frameworkとの統合、依存性の注入によるRedisTemplateクラスの提供
  • Pub/Subモデルのサポート

今回はこれらのフレームワークを用いて、セッション情報をRedisで共有するアプリケーションを実装してみましょう。具体的には、前回構築したローカル環境のRedisへのアクセスと、次回以降構築するAWS ECSコンテナでアプリケーションをデプロイし、ElastiCacheへアクセスができるようにアプリケーションを実装していきます。

なお、実際に作成したアプリケーションはGitHub上にコミットしています。以降で紹介するソースコードでは、import文など本質的でない記述を省略している部分があるので、実行コードを作成する場合は、適宜GitHub上のソースコードも参照してください。

実装に入る前に

Spring SessionとSpring Data Redisを使用するには、Mavenプロジェクトのpom.xmlで、spring-session-data-redisのライブラリを定義します。また、lettuceのDriverも定義しておいてください。

加えて、共有セッションへのアクセスを画面から確認するアプリケーションを作成するための「spring-boot-starter-web」、thymeleafテンプレートエンジンを使用するための「spring-boot-starter-thymeleaf」も追加しておきましょう。

<dependencies>
   <dependency>
     <groupId>org.springframework.session</groupId>
     <artifactId>spring-session-data-redis</artifactId>
   </dependency>
   <dependency>
     <groupId>io.lettuce</groupId>
     <artifactId>lettuce-core</artifactId>
   </dependency>
   <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>
</dependencies>

今回、アプリケーションは以下のコンポーネントで構成しますが、Spring SessionとSpring Data Redisで作成しなければならないクラスは以下の通りです。

コンポーネント 説明 必須
WebApp SpringBootアプリケーションを実行する起動クラス
MvcConfig Webアプリケーションの設定を行うクラス
RedisConfig Redisへの接続に関する設定クラス
ElastiCacheConfig ElastiCacheに接続する際に設定するクラス
SampleSession セッション情報に格納するモデルクラス
SampleController 画面からのリクエストを受け付け、セッション情報の更新を行い、結果をテンプレートエンジンに渡す

なお、thymeleafテンプレートエンジンに関する説明は省略しますが、必要に応じて、Thymeleaf公式ドキュメントMacchinetta Frameworkテンプレートエンジンを参照してください。ここでは、index.htmlからセッション情報を更新し、結果に遷移する画面を各々実装しています。

設定クラスの実装

それでは、クラスを実装していきましょう。まず最初に実装するのは、SpringBoot起動クラスと各種の設定クラスです。

@SpringBootApplicaitonアノテーションが付与された起動クラスは、同一パッケージにある@Configurationアノテーションが付与された設定クラスと、設定クラス内で@ComponentScanされたパッケージにあるクラスを読み取ります。今回は目的に応じて以下の4つに分類して定義します。

  • アプリケーションを起動するための起動クラス「WebApp」
  • SpringMVCの設定クラスであるWebMvcConfigurerを実装した設定クラス「MvcConfig」
  • Redisへアクセスを行う設定クラス「RedisConfig」
  • ElasticCache接続に必要な設定を行う設定クラス「ElastiCacheConfig」

アプリケーション起動クラスの実装は、以下の通りです。

package org.debugroom.mynavi.sample.aws.elasticache.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebApp {

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

起動クラスでは、@SpringBootApplicaitonアノテーションを設定し、SpringAppcalition.run()を実行するmain()メソッドを実装します。設定クラスは必ずしも複数である必要はなく、1つにまとめても動作上問題ありません。ただし、クラス名と役割を対応付けて作成しておいたほうが、後々設定内容で混乱することがないでしょう。

一方、同一パッケージに配置するMvcConfigクラスでは、HTMLやCSSなどの静的リソースのURLと実際のリソースの物理配置の対応付けの定義をResourceHandlerRegistryに追加しておきます。また、Controllerクラスを読み取るために、ComponentScanアノテーションにパッケージを指定しておきます。

package org.debugroom.mynavi.sample.aws.elasticache.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@ComponentScan("org.debugroom.mynavi.sample.aws.elasticache.app.web")
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
             .addResourceLocations("classpath:/static/");
    }

}

続いて、RedisConfigクラスとapplication.ymlでRedisのアクセス設定を行います。基本的に、Spring SessionでRedisを使用する場合、Mavenのpom.xmlでライブラリを追加した後、設定クラスに@EnableRedisHttpSessionアノテーションを付与するか、application.ymlでspring.session.store-typeプロパティを「redis」に設定にすることで、同等の効果を得ることができます。

spring:
  session:
    store-type: redis

application.ymlの設定があれば、Configクラスの設定は必ずしも必要ではありません。ただし、デフォルトではセッション情報保存時にJavaオブジェクトをシリアライズして保存するため、今回はRedisクライアントから中身を確認するためにJSON形式で保存するようにデフォルトのシリアライザを変更します。

package org.debugroom.mynavi.sample.aws.elasticache.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

}

また、ローカル環境のRedisでは問題ありませんが、ElastiCacheではconfigコマンドの実行が禁止されているため、「ConfigureRedisAction」を「NO_OP」に設定しておく必要があります。ElastiCache接続時に有効化すれば良いため、実行時にプロファイル「production」を指定するものとして、以下のようなConfigクラスを追加しておきましょう。

package org.debugroom.mynavi.sample.aws.elasticache.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.session.data.redis.config.ConfigureRedisAction;

@Profile("production")
@Configuration
public class ElastiCacheConfig {

    @Bean
    public ConfigureRedisAction configureRedisAction() {
        return ConfigureRedisAction.NO_OP;
    }

}

加えて、applicaiton.ymlではRedisに接続するためのIPアドレスとポート番号を「spring.redis.host」と「spring.redis.port」に指定しておく必要があります。

spring:
  redis:
    host: localhost
    port: 6379

また、ElastiCacheに接続するAWS環境では、ECSタスクに設定する環境変数からElastiCacheのエンドポイントを取得するよう、application-production.ymlを作成しておきます。

spring:
  redis:
    host: ${REDIS_CLUSTER_ENDPOINT:localhost}
    port: ${REDIS_CLUSTER_PORT:6379}

このapplication-production.ymlは、アプリケーション起動時にプロファイル「production」を指定することで有効化(applicaiton.ymlは上書き)される設定ファイルです。プロファイル名に合わせた設定ファイルを作成しておくことで設定を柔軟に切り替えることができます。

アプリケーションの設定に関する実装はここまでです。次回以降は、引き続きセッション共有処理に関わる実装を進めていきます。

著者紹介


川畑 光平(KAWABATA Kohei) - NTTデータ 課長代理

金融機関システム業務アプリケーション開発・システム基盤担当を経て、現在はソフトウェア開発自動化関連の研究開発・推進に従事。

Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなどさまざまな開発プロジェクト支援にも携わる。2019 APN AWS Top Engineers & Ambassadors選出。