¿Es así como se esperaría que se comporte Spring MVC?
A partir de Spring 4.3.7, así es como se comporta Spring MVC: usa HandlerExceptionResolverinstancias para manejar excepciones lanzadas por métodos de controlador.
De forma predeterminada, la configuración de MVC web registra un solo HandlerExceptionResolverbean, a HandlerExceptionResolverComposite, que
  delegados a una lista de otros HandlerExceptionResolvers.
Esos otros resolutores son
ExceptionHandlerExceptionResolver 
ResponseStatusExceptionResolver 
DefaultHandlerExceptionResolver 
registrado en ese orden. A los efectos de esta pregunta solo nos preocupamos ExceptionHandlerExceptionResolver.
  Una AbstractHandlerMethodExceptionResolverque resuelve excepciones a través de @ExceptionHandlermétodos.
En la inicialización del contexto, Spring generará un ControllerAdviceBeanpara cada @ControllerAdviceclase anotada que detecte. Los ExceptionHandlerExceptionResolverrecuperará del contexto y los ordenará usando el AnnotationAwareOrderComparatorque
  es una extensión de OrderComparatorque admite la Ordered
  interfaz de Spring, así como las anotaciones @Ordery @Priority, con un valor de orden proporcionado por una instancia Ordenada que anula un valor de anotación definido estáticamente (si lo hubiera).
Luego registrará un ExceptionHandlerMethodResolverpara cada una de estas ControllerAdviceBeaninstancias (mapeando los @ExceptionHandlermétodos disponibles a los tipos de excepción que deben manejar). Estos finalmente se agregan en el mismo orden a a LinkedHashMap(que conserva el orden de iteración).
Cuando ocurre una excepción, ExceptionHandlerExceptionResolveriterará a través de estos ExceptionHandlerMethodResolvery usará el primero que pueda manejar la excepción.
Entonces, el punto aquí es: si tiene una @ControllerAdvicecon una @ExceptionHandlerpara, Exceptionse registra antes que otra @ControllerAdviceclase con una @ExceptionHandlerpara una excepción más específica, como IOException, se llamará a la primera. Como se mencionó anteriormente, puede controlar ese orden de registro haciendo que su @ControllerAdviceclase anotada implemente Orderedo anotándola con @Ordero @Priorityy dándole un valor apropiado.
     
                
@ExceptionHandlermétodos dentro de a@ControllerAdvice, se elige el que maneja la superclase más específica de la excepción lanzada.Sotirios Delimanolis fue muy útil en su respuesta, en una investigación adicional encontramos que, en la primavera 3.2.4 de todos modos, el código que busca las anotaciones @ControllerAdvice también verifica la presencia de anotaciones @Order y ordena la lista de ControllerAdviceBeans.
El orden predeterminado resultante para todos los controladores sin la anotación @Order es Ordered # LOWEST_PRECEDENCE, lo que significa que si tiene un controlador que debe tener la prioridad más baja, TODOS sus controladores deben tener un orden superior.
A continuación, se muestra un ejemplo que muestra cómo tener dos clases de controlador de excepciones con las anotaciones ControllerAdvice y Order que pueden brindar respuestas adecuadas cuando se produce una UserProfileException o RuntimeException.
class UserProfileException extends RuntimeException { } @ControllerAdvice @Order(Ordered.HIGHEST_PRECEDENCE) class UserProfileExceptionHandler { @ExceptionHandler(UserProfileException) @ResponseBody ResponseEntity<ErrorResponse> handleUserProfileException() { .... } } @ControllerAdvice @Order(Ordered.LOWEST_PRECEDENCE) class DefaultExceptionHandler { @ExceptionHandler(RuntimeException) @ResponseBody ResponseEntity<ErrorResponse> handleRuntimeException() { .... } }¡Disfrutar!
fuente
El orden de los manejadores de excepciones se puede cambiar mediante la
@Orderanotación.Por ejemplo:
import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.web.bind.annotation.ControllerAdvice; @ControllerAdvice @Order(Ordered.HIGHEST_PRECEDENCE) public class CustomExceptionHandler { //... }@OrderEl valor de puede ser cualquier número entero.fuente
También encontré en la documentación que:
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-
Entonces, esto significa que si desea resolver este problema, deberá agregar su controlador de excepciones específico dentro del controlador que lanza esas excepciones. ANd para definir un único ControllerAdvice que maneja el manejador de excepciones predeterminado global.
Esto simplifica el proceso y no necesitamos la anotación de Pedido para manejar el problema.
fuente
Hay una situación similar en la excelente publicación " Manejo de excepciones en Spring MVC " en el blog de Spring, en la sección titulada Manejo de excepciones globales . Su escenario implica verificar las anotaciones ResponseStatus registradas en la clase de excepción y, si está presente, volver a lanzar la excepción para permitir que el marco las maneje. Es posible que pueda usar esta táctica general: intente determinar si hay un manejador más apropiado por ahí y volver a lanzar.
Alternativamente, hay algunas otras estrategias de manejo de excepciones cubiertas que podría considerar en su lugar.
fuente
Clase importante a manejar:
**@Order(Ordered.HIGHEST_PRECEDENCE)** public class FunctionalResponseEntityExceptionHandler { private final Logger logger = LoggerFactory.getLogger(FunctionalResponseEntityExceptionHandler.class); @ExceptionHandler(EntityNotFoundException.class) public final ResponseEntity<Object> handleFunctionalExceptions(EntityNotFoundException ex, WebRequest request) { logger.error(ex.getMessage() + " " + ex); ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false),HttpStatus.NOT_FOUND.toString()); return new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND); } }Otras excepciones con prioridad baja
@ControllerAdvice public class GlobalResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { private final Logger logger = LoggerFactory.getLogger(GlobalResponseEntityExceptionHandler.class); @ExceptionHandler(Exception.class) public final ResponseEntity<Object> handleAllException(Exception ex, WebRequest request) { logger.error(ex.getMessage()+ " " + ex); ExceptionResponse exceptionResponse= new ExceptionResponse(new Date(), ex.toString(), request.getDescription(false),HttpStatus.INTERNAL_SERVER_ERROR.toString()); } }fuente
también puede usar un valor numérico, como a continuación
@Order(value = 100)fuente