Würde man erwarten, dass sich Spring MVC so verhält?
Ab Spring 4.3.7 verhält sich Spring MVC folgendermaßen: Es verwendet HandlerExceptionResolver
Instanzen, um Ausnahmen zu behandeln, die von Handler-Methoden ausgelöst werden.
Standardmäßig registriert die Web-MVC-Konfiguration eine einzelne HandlerExceptionResolver
Bean, a HandlerExceptionResolverComposite
, die
delegiert an eine Liste von anderen HandlerExceptionResolvers
.
Diese anderen Resolver sind
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
in dieser Reihenfolge registriert. Für den Zweck dieser Frage kümmern wir uns nur ExceptionHandlerExceptionResolver
.
Eine AbstractHandlerMethodExceptionResolver
, die Ausnahmen durch @ExceptionHandler
Methoden auflöst .
Bei der Kontextinitialisierung generiert Spring ControllerAdviceBean
für jede mit @ControllerAdvice
Anmerkungen versehene Klasse eine. Das ExceptionHandlerExceptionResolver
ruft diese aus dem Kontext ab und sortiert sie mit AnnotationAwareOrderComparator
welcher
ist eine Erweiterung OrderComparator
, die die Spring- Ordered
Schnittstelle sowie die Annotationen @Order
und und unterstützt @Priority
, wobei ein Bestellwert, der von einer geordneten Instanz bereitgestellt wird, einen statisch definierten Annotationswert (falls vorhanden) überschreibt.
Anschließend wird ExceptionHandlerMethodResolver
für jede dieser ControllerAdviceBean
Instanzen eine registriert (Zuordnung der verfügbaren @ExceptionHandler
Methoden zu den Ausnahmetypen, die behandelt werden sollen). Diese werden schließlich in derselben Reihenfolge zu a hinzugefügt LinkedHashMap
(wodurch die Iterationsreihenfolge erhalten bleibt).
Wenn eine Ausnahme auftritt, ExceptionHandlerExceptionResolver
durchläuft der diese diese ExceptionHandlerMethodResolver
und verwendet die erste, die die Ausnahme behandeln kann.
Der Punkt hier ist also: Wenn Sie ein @ControllerAdvice
mit einem @ExceptionHandler
für das haben Exception
, wird es vor einer anderen @ControllerAdvice
Klasse mit einem @ExceptionHandler
für eine spezifischere Ausnahme registriert , wie zum Beispiel IOException
, dass das erste aufgerufen wird. Wie bereits erwähnt, können Sie diese Registrierungsreihenfolge steuern, indem Sie Ihre mit @ControllerAdvice
Anmerkungen versehene Klasse implementieren Ordered
oder mit @Order
oder mit Anmerkungen versehen @Priority
und ihr einen geeigneten Wert geben.
@ExceptionHandler
Methoden innerhalb von a@ControllerAdvice
diejenige ausgewählt, die die spezifischste Oberklasse der ausgelösten Ausnahme behandelt.Sotirios Delimanolis war in seiner Antwort sehr hilfreich. Bei weiteren Untersuchungen stellten wir fest, dass der Code, der nach @ ControlAdvice-Annotationen sucht, im Frühjahr 3.2.4 auch das Vorhandensein von @ Order-Annotationen überprüft und die Liste der ControllerAdviceBeans sortiert.
Die resultierende Standardreihenfolge für alle Controller ohne die Annotation @Order lautet Ordered # LOWEST_PRECEDENCE. Wenn Sie also einen Controller haben, der die niedrigste Priorität haben muss, müssen ALLE Ihre Controller eine höhere Reihenfolge haben.
In diesem Beispiel wird gezeigt, wie zwei Exception-Handler-Klassen mit ControllerAdvice- und Order-Annotationen erstellt werden, die geeignete Antworten liefern können, wenn entweder eine UserProfileException oder eine RuntimeException auftritt.
Genießen!
quelle
Die Reihenfolge der Ausnahmebehandlungsroutinen kann mithilfe der
@Order
Anmerkung geändert werden .Beispielsweise:
@Order
Der Wert kann eine beliebige Ganzzahl sein.quelle
Ich fand auch in der Dokumentation, dass:
https://docs.spring.io/spring-framework/docs/4.3.4.RELEASE/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.html#getExceptionHandlerMethod-org.springframework. web.method.HandlerMethod-java.lang.Exception-
Wenn Sie dieses Problem lösen möchten, müssen Sie Ihren spezifischen Ausnahmebehandler innerhalb des Controllers hinzufügen, der diese Ausnahme auslöst. ANd, um ein einziges ControllerAdvice zu definieren, das den globalen Standardausnahmehandler behandelt.
Dies vereinfacht den Vorgang und wir benötigen keine Auftragsanmerkung, um das Problem zu beheben.
quelle
Ähnliches gilt für den hervorragenden Beitrag " Ausnahmebehandlung im Frühjahr MVC " im Spring-Blog im Abschnitt " Globale Ausnahmebehandlung" . In diesem Szenario wird nach in der Ausnahmeklasse registrierten ResponseStatus-Annotationen gesucht und, falls vorhanden, die Ausnahme erneut ausgelöst, damit das Framework sie verarbeiten kann. Möglicherweise können Sie diese allgemeine Taktik anwenden - versuchen Sie festzustellen, ob es einen geeigneteren Handler gibt, und werfen Sie ihn neu.
Alternativ gibt es einige andere Strategien zur Ausnahmebehandlung, die Sie möglicherweise stattdessen betrachten.
quelle
Wichtige zu behandelnde Klasse:
Andere Ausnahmen mit niedriger Priorität
quelle
Sie können auch einen Zahlenwert wie unten verwenden
quelle