Play Framework 2.6(Scala)でCacheを使ってみた

## 概要
ScalaのPlay FrameworkでCacheを使ってみようとしたら、2.6で仕様が変わっていたので、2.6時点での情報整理とサンプルソースの作成をしてみました。

## 前提
Cacheに関する位置付けは[play framework2.1で認証情報を保持する](http://blog.beaglesoft.net/entry/%3Fp%3D510)にてまとめられています。また、2.6での変更点が[Cache APIs Migration](https://www.playframework.com/documentation/2.6.x/CacheMigration26)でまとめられています。この内容を前提として下記にサンプルソースを記します。

## サンプルソース
SyncCacheApiを使ったサンプルソースとなります、ユーザのログイン情報を管理するイメージでサンプルを書いています。使い方は従来のCacheとほぼ同様です。セッションキーの管理はControllerで、Cacheの管理はUtilを呼び出す形式としています。

【controllers】

```LoginController.scala
package controllers

import javax.inject._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import models._
import play.api.data.validation.Valid
import play.api.data.validation.Constraint
import play.api.data.validation.Invalid
import play.api.i18n.I18nSupport
import common.service.LoginUserTable
import models.LoginUser
import play.api.cache._
import models.LoginUser
import common.util.CacheUtil
import java.util.UUID

/**
 * Login時に使用するController
 */
@Singleton
class LoginController @Inject()( cache: SyncCacheApi, cc: ControllerComponents) extends AbstractController(cc) with I18nSupport {

  var loginUserTable:LoginUserTable = null
  
  // ログインフォーム
  val loginUserForm = Form( mapping("userid" -> text.verifying("ユーザIDを入力してください" , {!_.isEmpty()}) 
      , "userpw" -> text.verifying("パスワードを入力してください" , {!_.isEmpty()}) ) (LoginUser.apply)(LoginUser.unapply) 
                     )
  
  // ログイン画面の初期表示
  def loginInit() = Action { implicit request =>
     // セッションを初期化してログイン画面へ遷移
     CacheUtil.deleteSessionUser(cache , request.session.get("sessionKey"))
     Ok( views.html.login(loginUserForm) ).withNewSession
  }
  
  // ログイン画面のSubmit
  def loginSubmit() = Action { implicit request: Request[AnyContent] =>
     loginUserForm.bindFromRequest.fold(
         // 入力チェックNG
         errors => {           
           BadRequest( views.html.login(errors) )
         },
         // 入力チェックOK
         success => {
           // セッションキーを作成
           val sessionKey = UUID.randomUUID().toString;
           //CacheにUserをセット
           CacheUtil.setSessionUser(cache, loginUserTable ,sessionKey)
           // セッションにユーザをセットして次画面へ遷移
           Redirect("./loginSuccess").withSession("sessionKey" -> sessionKey)
         }
         
     )
  
  }
}
```
```LoginSuccessController.scala
package controllers

import javax.inject._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import models._
import play.api.data.validation.Valid
import play.api.data.validation.Constraint
import play.api.data.validation.Invalid
import play.api.i18n.I18nSupport
import common.service.LoginUserTable
import common.util.CacheUtil
import play.api.cache._

/**
 * Login成功時に使用するController
 */
@Singleton
class LoginSuccessController @Inject()( cache: SyncCacheApi, cc: ControllerComponents) extends AbstractController(cc) with I18nSupport {

  // Login成功画面の表示
  def loginSuccess() = Action { implicit request =>
    // セッションのチェック
    CacheUtil.getSessionUser(cache , request.session.get("sessionKey")) match {
      case Some(user) =>
        // Cacheのセッションの時間を更新するため再セット
        CacheUtil.setSessionUser(cache, user , request.session.get("sessionKey"))
        // Login成功画面へ遷移
        Ok( views.html.loginSuccess() )
      case None =>
        // ログイン画面へ遷移
        Redirect("./login")
    }
  }
}
```

【Util】

```CacheUtil.scala
package common.util

import common.service.LoginUserTable
import play.api.cache._
import scala.concurrent.duration._


object CacheUtil {
  
  // cacheにユーザをセット（キーがString）
  def setSessionUser(cache: SyncCacheApi , loginUserTable:LoginUserTable , sessionkey:String) = {
    //CacheにUserをセット（30分）
    cache.set(sessionkey, loginUserTable , 30.minutes)
  }
  
  // cacheにユーザをセット（キーがOption）
  def setSessionUser(cache: SyncCacheApi , loginUserTable:LoginUserTable , sessionkey:Option[String]) = {
    sessionkey match{
      case Some(key) =>
       //CacheにUserをセット（30分）
       cache.set(key, loginUserTable , 30.minutes)
      case None =>
        // 何もしない
    }
  }
  
  // cacheを削除
  def deleteSessionUser(cache: SyncCacheApi, sessionkey:Option[String])= {
    sessionkey match{
      case Some(key) =>
        //Cacheを削除
        cache.remove(key)
      case None =>
        // 何もしない
    }

  }
  
  // cacheを取得
  def getSessionUser( cache: SyncCacheApi , sessionkey:Option[String] ):Option[LoginUserTable]= {
    sessionkey match{
      case Some(key) =>
        // キャッシュからユーザオブジェクトを返す
        return cache.get[LoginUserTable](key)
      case None =>
        // Noneを返す
        return None
    }  
  }
}
```