springboot でセッション管理に redis を利用している場合、セッションIDが変わった際にセッションが切れるまでの間エラーになり続ける事象が発生することがある。
springboot2.7 時点ではこちらを参考にして以下のように対応していた。
@Configuration
public class SessionConfig extends RedisHttpSessionConfiguration {
@Autowired
RedisTemplate<Object, Object> redisTemplate;
@Bean
@Override
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
return super.springSessionRepositoryFilter(new SafeDeserializationRepository<>(sessionRepository, redisTemplate));
}
}
public class SafeDeserializationRepository<S extends ExpiringSession> implements SessionRepository<S> {
~略~
@Override
public S getSession(String id) {
try {
return delegate.getSession(id);
} catch(SerializationException e) {
// セッション ID が変わってデシリアライズエラーになった場合はその ID を削除
logger.info("Deleting non-deserializable session with key {}", id);
redisTemplate.delete(BOUNDED_HASH_KEY_PREFIX + id);
return null;
}
}
@Override
public void delete(String id) {
delegate.delete(id);
}
}
しかし springboot3.0 に上げると RedisHttpSessionConfiguration が SpringHttpSessionConfiguration を継承しなくなったので上記コードはビルドエラーとなる。
対応内容
- 直接 SpringHttpSessionConfiguration を継承する
-
@EnableRedisHttpSession
アノテーションを付与する - プロパティで
spring.main.allow-bean-definition-overriding = true
を設定する。
@Configuration
@EnableRedisHttpSession // 1.
public class SessionConfig extends SpringHttpSessionConfiguration { // 2.
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Bean
@Override
public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
return super.springSessionRepositoryFilter(new SafeDeserializationRepository<>(sessionRepository, redisTemplate));
}
}
application.yml
spring:
main:
allow-bean-definition-overriding: true # 3.