【Spring Boot】【Redis】メソッドをキャッシュする
はじめに
お世話になります、hosochinです
今回はSpring Bootでキャッシュの機能としてRedisを使ってみたいと思います
環境
- Redisをローカル環境に構築
- Spring Boot : 2.3.5
- Java : 1.8
- gradle : 6.9
Redisの構築手順についてはこちらでまとめています
実装
build.gradle
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.springframework.boot:spring-boot-starter-cache')
implementation('org.springframework.boot:spring-boot-starter-data-redis')
runtimeOnly('org.springframework.boot:spring-boot-devtools')
compileOnly("org.projectlombok:lombok:${lombokVersion}")
annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
testCompileOnly("org.projectlombok:lombok:${lombokVersion}")
testAnnotationProcessor("org.projectlombok:lombok:${lombokVersion}")
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
・なんか不要なものも入ってる気もしますが
・今回Redisでキャッシュ機能を実装するためにspring-boot-starter-cache、spring-boot-starter-data-redisを入れてます
・Spring Cacheについての詳細はこちら
・Spring Data Redisについての詳細はこちら
Mainクラス
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class TutorialSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(TutorialSpringBootApplication.class, args);
}
}
・@EnableCachingをつけることでキャッシュ機能を有効にしてやります
コントローラ
package com.example.demo.controller;
import com.example.demo.model.Message;
import com.example.demo.service.SampleService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class SampleController {
private final SampleService sampleService;
@GetMapping("/get/message")
public Message getMessage(@RequestParam(name = "message") String message) {
return sampleService.getMessage(message);
}
}
・動作確認用に簡単なコントローラクラスを作っておきます
・リクエストパラメータでmessageっていう適当な文字列を受け取って、自分で定義したMessageオブジェクトを返します
サービス
package com.example.demo.service;
import com.example.demo.model.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SampleService {
@Cacheable(cacheNames = "getMessage")
public Message getMessage(String message) {
log.info("キャッシュ効いてない, message=" + message);
return new Message(message, LocalDateTime.now());
}
}
・サービスクラスにキャッシュするメソッドを定義します
・@Cacheableをつけてやることでキャッシュの対象になります
・キャッシュがきいてるかどうかを確認するためログを仕込んでます
Messageクラス
package com.example.demo.model;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
@Getter
@Setter
@AllArgsConstructor
public class Message implements Serializable {
private String message;
private LocalDateTime updateTime;
}
・レスポンスに使用するMessageクラスです
・リクエストパラメータで受け取ったmessageに、なんとなく更新時間を入れてみました
・SerializableにしてやらないとRedisにつっこむときに怒られます
application.yml
spring:
redis:
host: localhost
port: 6379
・ローカルで起動しているRedisに接続する設定です
・Redisサーバ側の設定はデフォルトのままで特にいじってないです
動かしてみる
Redisとアプリケーションを起動してエントリポイント叩いてみます
以下のことが確認できたらうまくいってそうです
- 初回のリクエスト
- 仕込んだログが出力される = メソッドの中身が処理されている
- Redisを確認
- keyにキャッシュ名,引数の組み合わせが登録されている
- valueにメソッドのreturn値が登録されている
- 同じリクエストパラメータで2回目のリクエスト
- 仕込んだログが出力されない = メソッドの中身は処理されていない
- 1回目のレスポンスと同じレスポンスが返ってくる(updateTimeが同じ)
- リクエストパラメータを変えてリクエスト
- 仕込んだログが出力される = メソッドの中身が処理されている
- Redisを確認
- 新たにデータが追加されている
- Redisのデータを削除
- 再度リクエスト
- 仕込んだログが出力される = メソッドの中身が処理されている
1. 初回のリクエスト
$ curl "localhost:8080/get/message?message=test"
{"message":"test","updateTime":"2023-04-05T13:49:58.294"}
2. Redisを確認
(Redisにログインする)
redis-cli
127.0.0.1:6379> keys *
1) "getMessage::test"
↑ メソッド名と引数が登録されてる
3. 同じパラメータで2回目リクエスト
$ curl "localhost:8080/get/message?message=test"
{"message":"test","updateTime":"2023-04-05T13:49:58.294"}
↑ タイムスタンプが変わっていない!キャッシュが効いてる
4. リクエストパラメータを変えてリクエスト
$ curl "localhost:8080/get/message?message=test2"
{"message":"test2","updateTime":"2023-04-05T14:01:05.822"}
↑ 1回目と違う結果が得られた、キャッシュが効いてない
5. Redisを確認
127.0.0.1:6379> keys *
1) "getMessage::test2"
2) "getMessage::test"
↑ 2回目リクエストのパラメータが追加されてる
6. Redisのデータを削除
127.0.0.1:6379> flushdb
OK
7. 再度リクエスト
$ curl "localhost:8080/get/message?message=test"
{"message":"test","updateTime":"2023-04-05T14:04:42.193"}
↑ いい感じ
TTLを設定する
上記の例だとTTL(キャッシュの有効時間)が設定できていなかったですね
TTLを設定する場合はConfigクラスを書いてやります
package com.example.demo;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration(
// キャッシュ名を指定する
"getMessage",
// TTLを指定する(ここでは10秒に設定)
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10))
)
// それ以外のキャッシュしたいメソッドについても続けて書いていける
.withCacheConfiguration(
"そのほかにキャッシュしたいメソッド",
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))
);
}
}
実行してみると、10秒でキャッシュが消えることを確認できました!
ディスカッション
コメント一覧
まだ、コメントがありません