web-dev-qa-db-ja.com

Rest-fulアプリでの検証/例外応答の処理

そのため、_spring-boot_アプリケーション内であらゆる種類の例外を処理する際に問題に直面しています。基本的にプロジェクトは構造化されています:

back-end (services, repositories) <----- RestControllers <---- UI (React\Angular)

要点は、UIが_Rest API_に依存していること、残りのAPIが_Back-end services_に依存していることです

現在、_Rest API_は独自の[〜#〜] resources [〜#〜]および_back-end_サービスを独自のDTOを中心に設計されています。現在、検証は2つの場所で行われています:RestControllersおよびServicesUIは応答(検証エラー)を表示するだけです。

問題:RestControllerの通常の検証問題は、有効なresourceを取得することです。そして、これは_@Valid_、_JSR 303 Bean Validation_および_@ControllerAdvice_の組み合わせでうまく処理されます。そして、これは次のようなものに変換されます:[_field: ..._、_error: ..._] ...しかし、他の問題はどうですか? DB制約の例外。 ?そのため、検証はserviceレイヤーでも実行できますが、例外は[_field: ..._、_error: ..._]と同じ標準に準拠しなくなりました。また、serviceによってスローされた例外は、特定の応答に変換する必要があります[〜#〜] resource [〜#〜]。現在、複数のerror resourceがあり、これは成長し続けるだけです。

同様の状況で、そのような状況でのベストプラクティスは何ですか?

2
Xeperis

Springを使用した例を示しますRESTこの問題を処理するための組み込みの機能が非常に優れており、おそらく最も人気のあるJava REST現在実装されています。1つの戦略は、Spring @ ControllerAdvice アノテーションを使用することです。これにより、例外変換ロジックを含むクラスにアノテーションを付けて、リクエストの処理。

次に、クラス内のメソッドに @ ExceptionHandler および @ ResponseStatus アノテーションを付けて、さまざまな例外のロジックを定義できます。

たとえば、RESTの呼び出しが質問で説明されているように永続化レイヤーからのリソースの特定に失敗したときにスローされる例外を処理したい場合...

    @ExceptionHandler(EmptyResultDataAccessException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public SimpleErrorModel handleEmptyDataException(HttpServletRequest request, Exception exception) {
        LOGGER.debug(exception);
        return new SimpleErrorModel("Resource not found");
    }

または、DataIntegrityViolationExceptionがスローされた場合...

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public SimpleErrorModel handleDataIntegrityViolationException(HttpServletRequest request, Exception exception) {
        LOGGER.debug(exception);
        return new SimpleErrorModel("Data integrity violation");
    }

このように、例外がスローされると、Springは@ControllerAdviceアノテーションが付けられた適切なクラスを見つけて、正しい例外変換メソッドを検索します。このメソッドを解決し、メソッドのロジックを実行します。ここでは、次のようなSimpleErrorModelクラスを取得しています...

public class SimpleErrorModel {

    private String errorMessage;
    private String moreInfo;

    public SimpleErrorModel(String errorMessage) {
        this(errorMessage, "");
    }

    public SimpleErrorModel(String errorMessage, String moreInfo) {
        this.errorMessage = errorMessage;
        this.moreInfo = moreInfo;
    }
}

...次に、Spring RESTを介してシリアル化され、正しい応答コードでフロントエンドに返されます。HttpResponseオブジェクトをメソッドに渡して、好きなことを行うこともできます。 。

これは1つの戦略にすぎませんが、すべてのエラー処理ロジックを維持できるという利点があり、90%のユースケースで問題なく動作します。さらに細かい制御が必要な場合は、@ ControllerAdviceアノテーションに修飾子を追加できます...

    @ControllerAdvice(annotations = RestController.class)

...このハンドラが使用される注釈付きクラスを制限します。

1
HJCee