環境
macOS Catalina
Scala2.12.x
play2.6.x
やりたいこと
- アプリケーション内の計算式で利用する係数をファイルに持っておきたい。
- アクセスあるごとにファイルIOをしていると処理速度が遅くなるので、初回アクセス時のみファイルIOしたい。
ソリューション
- conf/配下にファイルを配置
- 初回アクセス時にファイルを読み込んで、値をシングルトンオブジェクトに保持する。(メモリに展開する)
シングルトンオブジェクトとは
同じプロセス内で、一つしか存在しないオブジェクトのこと。
一度作成されると同じプロセス内では、一度作成されたオブジェクトが使いまわされる。
Scalaでは、以下のようにobjectを定義するとシングルトンオブジェクトを定義できる。
case class SingletonSample(name: String)
object SingletonSample {
val singletonSample = SingletonSample("singleton")
}
SingletonSample.singletonSample
一度しか作成されないので、現在時刻などを管理するオブジェクトには使えない。(使ってもいいが、オブジェクトが作成された時刻が保持されるだけ)
case class DateObj(time: OffsetDateTime)
object Date {
val now = DateObj(OffsetDateTime.now)
}
Date.now //いつアクセスしてのも、オブジェクトが作成された時刻しか保持していない
実装例
case class FileData(file: List[String])
object FileData {
val file: FileData = FileData(
allCatch withApply {t: Throwable =>
logger.warn(s"$t")
logger.warn("ファイル読み込みできませんでした。")
Nil
} apply {
Source.fromInputStream(getClass.getClassLoader.getResourceAsStream("file.tsv")).getLines().toList
}
)
}
FileData.file
上記例では、ファイル全体をいったんオブジェクトに格納しているが、後々検索などをするのであれば、検索しやすいようにMapでデータを持つなどの加工はした方が良い。