そのため、_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
およびServices
UI
は応答(検証エラー)を表示するだけです。
問題:RestController
の通常の検証問題は、有効なresource
を取得することです。そして、これは_@Valid
_、_JSR 303 Bean Validation
_および_@ControllerAdvice
_の組み合わせでうまく処理されます。そして、これは次のようなものに変換されます:[_field: ...
_、_error: ...
_] ...しかし、他の問題はどうですか? DB制約の例外。 ?そのため、検証はservice
レイヤーでも実行できますが、例外は[_field: ...
_、_error: ...
_]と同じ標準に準拠しなくなりました。また、service
によってスローされた例外は、特定の応答に変換する必要があります[〜#〜] resource [〜#〜]。現在、複数のerror resourceがあり、これは成長し続けるだけです。
同様の状況で、そのような状況でのベストプラクティスは何ですか?
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)
...このハンドラが使用される注釈付きクラスを制限します。