2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spring Boot 3.2以降におけるNoResourceFoundException仕様変更と404エラー処理の対策

Posted at

はじめに

Spring Boot 3.2以降(内部的にはSpring Framework 6.1以降)では、存在しない静的リソースに対するリクエストが処理される際の挙動が変更され、従来の単純な404エラー返却ではなく、NoResourceFoundExceptionがスローされるようになりました。
本記事では、この仕様変更の背景と影響、そして404エラーを正しく返すために採用したNoResourceFoundException専用のグローバル例外ハンドラーによる対策について解説します。

仕様変更の概要

従来、Spring MVCでは存在しないURLへのリクエストに対して、HTTP 404エラーを直接返す処理が行われていました。しかし、Spring Framework 6.1以降、静的リソースの解決時にリソースが見つからなければ、内部でNoResourceFoundExceptionがスローされるようになりました。
この変更はエラー処理の一貫性と柔軟性を向上させるために導入されましたが、既存のグローバル例外ハンドラーがすべての例外(Exception)を一括処理している場合、意図せず500エラーとして扱われるという問題が発生します。

問題の背景

  • NoResourceFoundExceptionの仕様変更
    Spring Boot 3.2(Spring Framework 6.1)からは、静的リソースが存在しない場合にResourceHttpRequestHandlerNoResourceFoundExceptionをスローします。
  • 既存のグローバル例外ハンドラーの影響
    アプリケーション内で@ControllerAdviceを用いたグローバル例外ハンドラーが@ExceptionHandler(Exception.class)などで全例外を一括処理していると、NoResourceFoundExceptionもこのハンドラーでキャッチされ、結果としてHTTP 500エラーとなってしまいます。

対策:NoResourceFoundException専用のグローバル例外ハンドラーの実装

最も確実な対策は、NoResourceFoundException専用のハンドリングを行うことです。以下のような@ControllerAdviceクラスを実装することで、存在しない静的リソースへのアクセス時に正しくHTTP 404を返すことが可能になります。

import org.springframework.boot.web.servlet.error.NoResourceFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NoResourceFoundException.class)
    public ResponseEntity<Object> handleNoResourceFound(NoResourceFoundException ex) {
        // 必要に応じてログ出力やエラーメッセージの加工を行う
        String errorBody = "指定されたリソースが見つかりませんでした。";
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorBody);
    }
}

このハンドラーを導入することで、静的リソースが存在しない場合にNoResourceFoundExceptionがスローされても、グローバルハンドラーがキャッチし、HTTP 404として適切なレスポンスを返すようになります。

まとめ

Spring Boot 3.2以降では、静的リソースが見つからない場合にNoResourceFoundExceptionがスローされる仕様変更が導入され、既存のグローバル例外ハンドラーで全例外を一括処理していると、本来404とすべきリクエストが500エラーとして扱われるケースが発生します。
私の場合、デフォルトハンドリング(方法2)やResourceHandlerの優先順位調整(方法3)はうまくいかなかったため、NoResourceFoundException専用のグローバル例外ハンドラーを実装する方法で問題を解決しました。
この方法により、存在しないリソースへのリクエストで正しく404エラーが返されるようになり、ユーザやクローラに対して意図した動作を提供できるようになりました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?