30秒で解決する方法
HttpRequestMethodNotSupportedExceptionは、リクエストタイプ(POSTなど)がSpringコントローラーで定義されているもの(GETなど)と一致しない場合に発生します。すぐに修正するためのチェックリストは以下の通りです。 slums
- アノテーションを確認する: データを送信する場合は
@PostMappingを使用してください。 - URLを確認する: 誤ってGET専用のエンドポイントにアクセスしている可能性があります。
- クライアントを検証する: Postman、cURL、またはフロントエンドがデフォルトでGETになっていないか確認してください。
なぜこの問題が発生するのか?
Spring MVCは、HandlerMappingを利用して、入ってきたトラフィックを@RestControllerに誘導します。これは交通整理のような役割を果たし、URLパスとHTTP動詞(GET、POST、PUTなど)の2つをチェックします。 slums
この例外が発生する場合、Springは実際には一致するURLを見つけています。問題は、呼び出している特定のメソッドが、送信したHTTP動詞を処理するように設定されていないことです。例えば、@GetMappingエンドポイントをPOSTリクエストで呼び出すと、Springはそれをブロックします。その後、この例外をスローし、クライアントに405 Method Not Allowedステータスコードを返します。
よくある原因
1. アノテーションの不一致
これはケースの約90%における原因です。データを保存するつもりでも、誤って間違ったマッピングアノテーションを使用している可能性があります。
問題のあるコード:
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// このエンドポイントはGETのみをリッスンします
@GetMapping("/save")
public ResponseEntity<String> saveUser(@RequestBody User user) {
return ResponseEntity.ok("User saved");
}
}
POSTを/api/v1/users/saveに送信すると、失敗します。なぜでしょうか?それは、@GetMappingがデータの読み取りのみを許可し、投稿(POST)を許可していないからです。
修正後のコード:
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@PostMapping("/save") // これでPOSTリクエストを受け付けるようになります
public ResponseEntity<String> saveUser(@RequestBody User user) {
return ResponseEntity.status(201).body("User created with ID: 101");
}
}
2. タイポ(打ち間違い)とパス変数
URLのわずかなタイポにより、Springが間違ったメソッドに誘導されることがあります。以下の2つのエンドポイントを考えてみましょう。
GET /api/products/{id}(製品を1つ取得)POST /api/products(新しい製品を作成)
誤ってPOST /api/products/123を呼び出すと、SpringはパスをGETメソッドに一致させます。その後、ID指定のパスに対してPOSTを使用しようとしていることを検知し、その特定のルートがPOSTをサポートしていないため、例外をスローします。
3. Spring SecurityにおけるCSRF保護
Spring SecurityはデフォルトでCSRF(クロスサイトリクエストフォージェリ)保護を有効にしています。通常、これは403 Forbiddenエラーを引き起こします。しかし、カスタムセキュリティフィルタや内部リダイレクトによって実際の問題が隠され、結果として紛らわしい405エラーが発生することがあります。
JWTを使用したステートレスなREST APIを構築している場合は、設定でCSRFを安全に無効化できます:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
修正を確認する方法
ブラウザは結果をキャッシュしたり、デフォルトでGETを使用したりすることが多いため、テストにブラウザを使用しないでください。サーバーが何を返しているかを正確に確認するには、curlを使用します。
ターミナルで以下のコマンドを実行してください:
curl -i -X POST http://localhost:8080/api/v1/users/save \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'
修正が成功すると、200 OKまたは201 Createdが返されます。それでも失敗する場合は、-iフラグを使用することで、サーバーから返された正確なヘッダーとステータスコードを確認できます。
ログをプロのように読み解く
コンソール出力を確認してください。Springはこの例外を解決する際に、明確なヒントを提供します:
WARN 45210 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported. Available methods: [GET]]
このログは情報の宝庫です。Available methods(利用可能なメソッド)を明示的にリストアップしています。もし[GET]と表示されているなら、コントローラーに@PostMappingアノテーションが不足していることが確実に分かります。
次のステップ
- Spring @RequestMapping ドキュメントを確認する。
- フロントエンドのfetch/axios呼び出しで、正しい
methodプロパティが指定されていることを確認する。 - リソースのコレクションと個別のアイテムの間で混乱を避けるために、APIパスを標準化する。

