Problem Spring Web ist eine Reihe von Bibliotheken, mit denen application/problem+json -Antworten aus einer Frühlingsanwendung einfach produziert werden können. Es füllt eine Nische, indem es die Problembibliothek und entweder die Ausnahmebehandlung von Spring Web -MVC oder die Ausnahmebehandlung von Spring WebFlux verbindet, damit sie nahtlos zusammenarbeiten, während sie nur minimale zusätzliche Entwickleranstrengungen erfordern. Dabei zielt es darauf ab, eine kleine, aber sich wiederholende Aufgabe auszuführen - ein für alle Mal.
Die Art und Weise, wie diese Bibliothek funktioniert, basiert auf den Beratungsmerkmalen . Eine Beratungsmerkmal ist eine kleine, wiederverwendbare @ExceptionHandler die als Standardmethode implementiert ist, die in einer einzelnen Methodenschnittstelle platziert ist. Diese Beratungsmerkmale können frei kombiniert werden und müssen keine gemeinsame Basisklasse für Ihr @ControllerAdvice verwenden.
? Bitte besuchen Sie BEADUNG: Eine Anleitung zur Problem der Spring -Webbibliothek für eine detaillierte Einführung!
Der von AdviceTrait bereitgestellte Problembehandlungsverfahren ist auf eine Weise erstellt, die bei Bedarf eine Anpassung ermöglicht. Alle folgenden Aspekte (und mehr) können angepasst werden, indem die entsprechende Beratungs -Merkmalschnittstelle implementiert wird:
| Aspekt | Methode (en) | Standard |
|---|---|---|
| Schaffung | AdviceTrait.create(..) | |
| Protokollierung | AdviceTrait.log(..) | 4xx als WARN , 5xx als ERROR einschließlich Stack Trace |
| Inhaltsverhandlung | AdviceTrait.negotiate(..) | application/json , application/*+json , application/problem+json und application/x.problem+json |
| Zurückgreifen | AdviceTrait.fallback(..) | application/problem+json |
| Nachbearbeitung | AdviceTrait.process(..) | n / A |
Das folgende Beispiel passt das MissingServletRequestParameterAdviceTrait an, indem das Problem ein parameter hinzugefügt wird:
@ ControllerAdvice
public class MissingRequestParameterExceptionHandler implements MissingServletRequestParameterAdviceTrait {
@ Override
public ProblemBuilder prepare ( Throwable throwable , StatusType status , URI type ) {
var exception = ( MissingServletRequestParameterException ) throwable ;
return Problem . builder ()
. withTitle ( status . getReasonPhrase ())
. withStatus ( status )
. withDetail ( exception . getMessage ())
. with ( "parameter" , exception . getParameterName ());
}
}Angenommen, es gibt einen solchen Controller:
@ RestController
@ RequestMapping ( "/products" )
class ProductsResource {
@ RequestMapping ( method = GET , value = "/{productId}" , produces = APPLICATION_JSON_VALUE )
public Product getProduct ( String productId ) {
// TODO implement
return null ;
}
@ RequestMapping ( method = PUT , value = "/{productId}" , consumes = APPLICATION_JSON_VALUE )
public Product updateProduct ( String productId , Product product ) {
// TODO implement
throw new UnsupportedOperationException ();
}
}Die folgenden HTTP -Anfragen erzeugen die entsprechende Antwort jeweils:
GET /products/123 HTTP/1.1
Accept: application/xml HTTP/1.1 406 Not Acceptable
Content-Type: application/problem+json
{
"title" : " Not Acceptable " ,
"status" : 406 ,
"detail" : " Could not find acceptable representation "
} POST /products/123 HTTP/1.1
Content-Type: application/json
{} HTTP/1.1 405 Method Not Allowed
Allow: GET
Content-Type: application/problem+json
{
"title" : " Method Not Allowed " ,
"status" : 405 ,
"detail" : " POST not supported "
}Bevor Sie fortfahren , lesen Sie bitte den Abschnitt über Stapelspuren und Kausalketten in Zalando/Problem.
Wenn Sie Stapelspuren aktivieren möchten, konfigurieren Sie bitte Ihr ProblemModule wie folgt:
ObjectMapper mapper = new ObjectMapper ()
. registerModule ( new ProblemModule (). withStackTraces ());Kausale Probleme von Problemen sind standardmäßig deaktiviert , können jedoch bei gewünschtem Wunsch überschrieben werden:
@ ControllerAdvice
class ExceptionHandling implements ProblemHandling {
@ Override
public boolean isCausalChainsEnabled () {
return true ;
}
} Beachten Sie , da Sie zu diesem Zeitpunkt den vollen Zugriff auf den Anwendungskontext haben, können Sie die Konfiguration auf Ihre application.yml externalisieren und sogar entscheiden, Spring's server.error.include-stacktrace Eigenschaft wiederzuverwenden.
Das Aktivieren von Merkmalen, Kausalketten und Stacktraces ergibt:
{
" title " : " Internal Server Error " ,
" status " : 500,
" detail " : " Illegal State " ,
" stacktrace " : [
" org.example.ExampleRestController.newIllegalState(ExampleRestController.java:96) " ,
" org.example.ExampleRestController.nestedThrowable(ExampleRestController.java:91) "
],
" cause " : {
" title " : " Internal Server Error " ,
" status " : 500,
" detail " : " Illegal Argument " ,
" stacktrace " : [
" org.example.ExampleRestController.newIllegalArgument(ExampleRestController.java:100) " ,
" org.example.ExampleRestController.nestedThrowable(ExampleRestController.java:88) "
],
" cause " : {
" title " : " Internal Server Error " ,
" status " : 500,
" detail " : " Null Pointer " ,
" stacktrace " : [
" org.example.ExampleRestController.newNullPointer(ExampleRestController.java:104) " ,
" org.example.ExampleRestController.nestedThrowable(ExampleRestController.java:86) " ,
" sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) " ,
" sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) " ,
" sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) " ,
" java.lang.reflect.Method.invoke(Method.java:483) " ,
" org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) " ,
" org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) " ,
" org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) " ,
" org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) " ,
" org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) " ,
" org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) " ,
" org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) " ,
" org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) " ,
" org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) " ,
" org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) " ,
" org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) " ,
" org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) " ,
" org.junit.runners.ParentRunner.run(ParentRunner.java:363) " ,
" org.junit.runner.JUnitCore.run(JUnitCore.java:137) " ,
" com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) " ,
" com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234) " ,
" com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74) "
]
}
}
} Die Spring ermöglicht es, den Umfang eines @ControllerAdvice auf eine bestimmte Teilmenge von Controllern zu beschränken:
@ ControllerAdvice ( assignableTypes = ExampleController . class )
public final class ExceptionHandling implements ProblemHandlingAuf diese Weise verlieren Sie die Fähigkeit, bestimmte Arten von Ausnahmen zu handhaben, nämlich:
HttpRequestMethodNotSupportedExceptionHttpMediaTypeNotAcceptableExceptionHttpMediaTypeNotSupportedExceptionNoHandlerFoundException Wir erben diese Einschränkung aus dem Frühling und empfehlen daher, einen uneingeschränkten @ControllerAdvice zu verwenden.
Wenn Sie Fragen, Bedenken, Fehlerberichte usw. haben, stellen Sie bitte ein Problem in den Ausgaben -Tracker dieses Repositorys ein.
Um einen Beitrag zu leisten, stellen Sie einfach eine Pull-Anfrage und fügen Sie eine kurze Beschreibung (1-2 Sätze) Ihrer Addition oder Änderung hinzu. Weitere Informationen finden Sie in den Beitragsrichtlinien.