Ich möchte eine generische Methode zum Verwalten von 5xx-Fehlercodes verwenden. Sagen wir speziell den Fall, dass die Datenbank in meiner gesamten Frühjahrsanwendung nicht verfügbar ist. Ich möchte einen hübschen Fehler json anstelle eines Stack-Trace.
Für die Controller habe ich eine @ControllerAdvice
Klasse für die verschiedenen Ausnahmen und dies fängt auch den Fall ein, dass die Datenbank mitten in der Anfrage stoppt. Aber das ist nicht alles. Ich habe auch zufällig eine benutzerdefinierte CorsFilter
Erweiterung OncePerRequestFilter
und dort, wenn ich doFilter
anrufe, bekomme ich die CannotGetJdbcConnectionException
und es wird nicht von der verwaltet @ControllerAdvice
. Ich habe online einige Dinge gelesen, die mich nur verwirrter gemacht haben.
Ich habe also viele Fragen:
- Muss ich einen benutzerdefinierten Filter implementieren? Ich fand das
ExceptionTranslationFilter
aber das handhabt nurAuthenticationException
oderAccessDeniedException
. - Ich dachte daran, meine eigenen zu implementieren
HandlerExceptionResolver
, aber das ließ mich zweifeln, ich habe keine benutzerdefinierte Ausnahme zu verwalten, es muss einen offensichtlicheren Weg als diesen geben. Ich habe auch versucht, einen try / catch hinzuzufügen und eine Implementierung von aufzurufenHandlerExceptionResolver
(sollte gut genug sein, meine Ausnahme ist nichts Besonderes), aber dies gibt nichts in der Antwort zurück, ich erhalte einen Status 200 und einen leeren Körper.
Gibt es eine gute Möglichkeit, damit umzugehen? Vielen Dank
quelle
Antworten:
Das habe ich also getan:
Ich lese die Grundlagen über Filter hier und ich herausgefunden, dass ich einen benutzerdefinierten Filter erstellen , die zuerst in der Filterkette sein wird und versuchen Fang haben alle Laufzeitausnahmen zu fangen , die dort auftreten könnten. Dann muss ich den JSON manuell erstellen und in die Antwort einfügen.
Also hier ist mein benutzerdefinierter Filter:
Und dann habe ich es in der web.xml vor dem hinzugefügt
CorsFilter
. Und es funktioniert!quelle
Ich wollte eine Lösung anbieten, die auf der Antwort von @kopelitsa basiert . Die Hauptunterschiede sind:
HandlerExceptionResolver
.Zunächst müssen Sie sicherstellen, dass Sie über eine Klasse verfügen, die Ausnahmen behandelt, die in einem regulären RestController / Controller auftreten (eine Klasse, die mit
@RestControllerAdvice
oder@ControllerAdvice
und Methoden mit Anmerkungen versehen ist@ExceptionHandler
). Dies behandelt Ihre Ausnahmen, die in einem Controller auftreten. Hier ist ein Beispiel mit dem RestControllerAdvice:Um dieses Verhalten in der Spring Security-Filterkette wiederzuverwenden, müssen Sie einen Filter definieren und in Ihre Sicherheitskonfiguration einbinden. Der Filter muss die Ausnahme zur oben definierten Ausnahmebehandlung umleiten. Hier ist ein Beispiel:
Der erstellte Filter muss dann zur SecurityConfiguration hinzugefügt werden. Sie müssen es sehr früh in die Kette einhängen, da nicht alle Ausnahmen des vorhergehenden Filters abgefangen werden. In meinem Fall war es vernünftig, es vor dem hinzuzufügen
LogoutFilter
. Die Standardfilterkette und ihre Reihenfolge finden Sie in den offiziellen Dokumenten . Hier ist ein Beispiel:quelle
Ich bin selbst auf dieses Problem gestoßen und habe die folgenden Schritte ausgeführt, um mein
ExceptionController
mit Anmerkungen versehenes Problem@ControllerAdvise
fürExceptions
die Verwendung in einem registrierten Filter wiederzuverwenden .Es gibt offensichtlich viele Möglichkeiten, Ausnahmen zu behandeln, aber in meinem Fall wollte ich, dass die Ausnahme von meinem behandelt wird,
ExceptionController
weil ich hartnäckig bin und auch nicht den gleichen Code kopieren / einfügen möchte (dh ich habe etwas Verarbeitung / Protokollierung Code inExceptionController
). Ich möchte die schöneJSON
Antwort zurückgeben, genau wie die restlichen Ausnahmen, die nicht von einem Filter ausgelöst wurden.Wie auch immer, ich habe es geschafft, meine zu nutzen,
ExceptionHandler
und ich musste ein bisschen mehr tun, wie unten in Schritten gezeigt:Schritte
@ControllerAdvise
MyExceptionController behandeltBeispielcode
Und jetzt der Beispiel-Spring-Controller, der
Exception
in normalen Fällen behandelt wird (dh Ausnahmen, die normalerweise nicht in der Filterebene ausgelöst werden, die wir für Ausnahmen verwenden möchten, die in einem Filter ausgelöst werden).Teilen Sie die Lösung mit denen, die sie
ExceptionController
fürExceptions
einen Filter verwenden möchten .quelle
@Component
Klasse extrahieren und diese im Filter und in verwenden Der Controller.answer
dies einer der Wege! Ich habe nicht behauptet, dass es der beste Weg ist. Vielen Dank für das Teilen Ihres Anliegens @psv Ich bin sicher, die Community würde die Lösung, die Sie im Sinn haben, schätzen :)Also, hier ist, was ich basierend auf einer Zusammenführung der obigen Antworten getan habe ... Wir hatten bereits eine
GlobalExceptionHandler
Annotation mit@ControllerAdvice
und ich wollte auch einen Weg finden, diesen Code wiederzuverwenden, um Ausnahmen zu behandeln, die von Filtern stammen.Die einfachste Lösung, die ich finden konnte, bestand darin, den Ausnahmebehandler in Ruhe zu lassen und einen Fehlercontroller wie folgt zu implementieren:
Fehler, die durch Ausnahmen verursacht werden, werden zuerst durchlaufen
ErrorController
und durch erneutes Auslösen aus einem@Controller
Kontext an den Ausnahmebehandler weitergeleitet , während andere Fehler (die nicht direkt durch eine Ausnahme verursacht werden)ErrorController
ohne Änderung durchlaufen werden.Gibt es Gründe, warum dies eigentlich eine schlechte Idee ist?
quelle
@Override public String getErrorPath() { return null; }
Wenn Sie einen generischen Weg wünschen, können Sie eine Fehlerseite in web.xml definieren:
Und fügen Sie Mapping in Spring MVC hinzu:
quelle
Dies ist meine Lösung, indem der Standard-Spring-Boot- / Fehlerhandler überschrieben wird
quelle
Nur um die anderen guten Antworten zu ergänzen, da ich kürzlich eine einzelne Fehler- / Ausnahmebehandlungskomponente in einer einfachen SpringBoot-App haben wollte, die Filter enthält, die Ausnahmen auslösen können, wobei andere Ausnahmen möglicherweise von Controller-Methoden ausgelöst werden.
Glücklicherweise scheint es nichts zu geben, das Sie daran hindert, Ihre Controller-Hinweise mit einer Überschreibung des Standard-Fehlerbehandlungsprogramms von Spring zu kombinieren, um konsistente Antwortnutzdaten bereitzustellen, Logik gemeinsam zu nutzen, Ausnahmen von Filtern zu überprüfen, bestimmte vom Dienst ausgelöste Ausnahmen abzufangen usw.
Z.B
quelle
Wenn Sie einen Anwendungsstatus testen möchten und im Falle eines Problems einen HTTP-Fehler zurückgeben möchten, würde ich einen Filter vorschlagen. Der folgende Filter verarbeitet alle HTTP-Anforderungen. Die kürzeste Lösung in Spring Boot mit einem Javax-Filter.
In der Implementierung können verschiedene Bedingungen sein. In meinem Fall testet der applicationManager, ob die Anwendung bereit ist.
quelle
Nachdem ich die in den obigen Antworten vorgeschlagenen Methoden durchgelesen hatte, entschied ich mich, die Authentifizierungsausnahmen mithilfe eines benutzerdefinierten Filters zu behandeln. Ich konnte den Antwortstatus und die Codes mithilfe einer Fehlerantwortklasse mit der folgenden Methode verarbeiten.
Ich habe einen benutzerdefinierten Filter erstellt und meine Sicherheitskonfiguration mithilfe der addFilterAfter-Methode geändert und nach der CorsFilter-Klasse hinzugefügt.
SecurityConfig-Klasse
ErrorResponse-Klasse
quelle
Sie können die folgende Methode im catch-Block verwenden:
Beachten Sie, dass Sie einen beliebigen HttpStatus-Code und eine benutzerdefinierte Nachricht verwenden können.
quelle
Es ist seltsam, weil @ControllerAdvice funktionieren sollte. Fangen Sie die richtige Ausnahme?
Versuchen Sie auch, diese Ausnahme in CorsFilter abzufangen und 500 Fehler zu senden
quelle
Filter
darf nicht erwischt werden,@ControllerAdvice
da in möglicherweise nicht zu erreichen istDispatcherServlet
.Sie müssen hierfür keinen benutzerdefinierten Filter erstellen. Wir haben dieses Problem gelöst, indem wir benutzerdefinierte Ausnahmen erstellt haben, die die ServletException erweitern (die von der in der Deklaration gezeigten doFilter-Methode ausgelöst wird). Diese werden dann von unserem globalen Fehlerbehandler abgefangen und verarbeitet.
bearbeiten: Grammatik
quelle