1. 概要

Spring Boot 2と新しいノンブロッキングサーバーNettyでは、サーブレットコンテキストAPIがなくなったため、新しいスタックを使用してさまざまな種類のHTTPステータスコードを表現する方法について説明します。

2. セマンティックレスポンスステータス

標準のRESTfulプラクティスに従ってください。当然、APIのセマンティクスを適切に表現するには、HTTPステータスコードの全範囲を利用する必要があります。

2.1. デフォルトの返品ステータス

もちろん、すべてがうまくいくと、デフォルトの応答ステータスは 200(OK)になります。

@GetMapping(
  value = "/ok",
  produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public Flux<String> ok() {
    return Flux.just("ok");
}

2.2. 注釈の使用

メソッドに@ResponseStatusアノテーションを追加して、デフォルトのリターンステータスを変更できます。

@GetMapping(
  value = "/no-content",
  produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
@ResponseStatus(HttpStatus.NO_CONTENT)
public Flux<String> noContent() {
    return Flux.empty();
}

2.3. プログラムでステータスを変更する

場合によっては、サーバーの動作に応じて、デフォルトで使用されるプレフィックス付きの戻りステータスやアノテーションではなく、プログラムで返されるステータスを変更することを決定できます。

ServerHttpResponse をメソッドに直接挿入することで、次のことを実現できます。

@GetMapping(
  value = "/accepted",
  produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public Flux<String> accepted(ServerHttpResponse response) {
    response.setStatusCode(HttpStatus.ACCEPTED);
    return Flux.just("accepted");
}

これで、実装で返すHTTPステータスコードを選択できます。

2.4. 例外をスローする

例外をスローするたびに、デフォルトのHTTP戻りステータスが省略され、Springはそれを処理するための例外ハンドラーを見つけようとします。

@GetMapping(
  value = "/bad-request"
)
public Mono<String> badRequest() {
    return Mono.error(new IllegalArgumentException());
}
@ResponseStatus(
  value = HttpStatus.BAD_REQUEST,
  reason = "Illegal arguments")
@ExceptionHandler(IllegalArgumentException.class)
public void illegalArgumentHandler() {
    // 
}

その方法の詳細については、Baeldungエラー処理の記事を必ず確認してください。

2.5. ResponseEntityを使用

ここで、興味深い代替手段であるResponseEntityクラスを簡単に見てみましょう。

これにより、非常に便利な流暢なAPIを使用して、返すHTTPステータスを選択したり、応答をさらにカスタマイズしたりできます。

@GetMapping(
  value = "/unauthorized"
)
public ResponseEntity<Mono<String>> unathorized() {
    return ResponseEntity
      .status(HttpStatus.UNAUTHORIZED)
      .header("X-Reason", "user-invalid")
      .body(Mono.just("unauthorized"));
}

2.6. 機能エンドポイントを使用

Spring 5では、機能的な方法でエンドポイントを定義できるため、プログラムでデフォルトのHTTPステータスを変更することもできます。

@Bean
public RouterFunction<ServerResponse> notFound() {
    return RouterFunctions
      .route(GET("/statuses/not-found"),
         request -> ServerResponse.notFound().build());
}

3. 結論

HTTP APIを実装する場合、フレームワークは、クライアントに公開しているステータスコードをインテリジェントに処理するためのいくつかのオプションを提供します。

この記事は、これらを調査し、クリーンでRESTfulなセマンティクスを使用して表現力豊かでフレンドリーなAPIを展開する方法を理解するための良い出発点となるはずです。

もちろん、このチュートリアルで使用されている完全なコード例は、Githubから入手できます。