Saltar al contenido

Anulando el comportamiento de manejo para las excepciones estándar de Spring MVC

No busques más por internet porque llegaste al lugar indicado, tenemos la respuesta que deseas pero sin liarte.

Solución:

Spring MVC configura de hecho un controlador de excepciones para usted.
Por defecto, DefaultHandlerExceptionResolver se utiliza como se indica en la clase javadoc:

Implementación predeterminada del HandlerExceptionResolver interfaz que resuelve las excepciones estándar de Spring y las traduce a los códigos de estado HTTP correspondientes.

Este solucionador de excepciones está habilitado de forma predeterminada en el Spring común
org.springframework.web.servlet.DispatcherServlet.
Eso es correcto para los controladores MVC.

Pero para los controladores de excepciones para controladores REST (su requisito aquí), Spring confía en el ResponseEntityExceptionHandler clase.
La primera clase tiene métodos que regresan. ModelAndViews mientras que la segunda clase tiene métodos que devuelven ReponseEntitys.

Puede definir un controlador de excepciones personalizado anotando su clase con @ControllerAdvice en ambos casos (controladores MVC y REST) ​​pero como su requisito es para controladores REST, centrémonos en eso.

Además de anotar un controlador de excepciones personalizado con @ControllerAdvice, también puede hacer eso para extender una clase de controlador de excepciones base como ResponseEntityExceptionHandler para anular algunos comportamientos.
ResponseEntityExceptionHandler implementaciones permite conocer todas las excepciones realmente manejadas y mapeadas. Mira el handleException() método que es el método de fachada de la ResponseEntityExceptionHandler clase :

/**
 * Provides handling for standard Spring MVC exceptions.
 * @param ex the target exception
 * @param request the current request
 */
@ExceptionHandler(
        HttpRequestMethodNotSupportedException.class,
        HttpMediaTypeNotSupportedException.class,
        HttpMediaTypeNotAcceptableException.class,
        MissingPathVariableException.class,
        MissingServletRequestParameterException.class,
        ServletRequestBindingException.class,
        ConversionNotSupportedException.class,
        TypeMismatchException.class,
        HttpMessageNotReadableException.class,
        HttpMessageNotWritableException.class,
        MethodArgumentNotValidException.class,
        MissingServletRequestPartException.class,
        BindException.class,
        NoHandlerFoundException.class,
        AsyncRequestTimeoutException.class
    )
@Nullable
public final ResponseEntity handleException(Exception ex, WebRequest request) 
    HttpHeaders headers = new HttpHeaders();
    if (ex instanceof HttpRequestMethodNotSupportedException) 
        HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
        return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);
    
    else if (ex instanceof HttpMediaTypeNotSupportedException) 
        HttpStatus status = HttpStatus.UNSUPPORTED_MEDIA_TYPE;
        return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, headers, status, request);
    
    else if (ex instanceof HttpMediaTypeNotAcceptableException) 
        HttpStatus status = HttpStatus.NOT_ACCEPTABLE;
        return handleHttpMediaTypeNotAcceptable((HttpMediaTypeNotAcceptableException) ex, headers, status, request);
    
    else if (ex instanceof MissingPathVariableException) 
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleMissingPathVariable((MissingPathVariableException) ex, headers, status, request);
    
    else if (ex instanceof MissingServletRequestParameterException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMissingServletRequestParameter((MissingServletRequestParameterException) ex, headers, status, request);
    
    else if (ex instanceof ServletRequestBindingException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleServletRequestBindingException((ServletRequestBindingException) ex, headers, status, request);
    
    else if (ex instanceof ConversionNotSupportedException) 
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleConversionNotSupported((ConversionNotSupportedException) ex, headers, status, request);
    
    else if (ex instanceof TypeMismatchException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleTypeMismatch((TypeMismatchException) ex, headers, status, request);
    
    else if (ex instanceof HttpMessageNotReadableException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleHttpMessageNotReadable((HttpMessageNotReadableException) ex, headers, status, request);
    
    else if (ex instanceof HttpMessageNotWritableException) 
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleHttpMessageNotWritable((HttpMessageNotWritableException) ex, headers, status, request);
    
    else if (ex instanceof MethodArgumentNotValidException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMethodArgumentNotValid((MethodArgumentNotValidException) ex, headers, status, request);
    
    else if (ex instanceof MissingServletRequestPartException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleMissingServletRequestPart((MissingServletRequestPartException) ex, headers, status, request);
    
    else if (ex instanceof BindException) 
        HttpStatus status = HttpStatus.BAD_REQUEST;
        return handleBindException((BindException) ex, headers, status, request);
    
    else if (ex instanceof NoHandlerFoundException) 
        HttpStatus status = HttpStatus.NOT_FOUND;
        return handleNoHandlerFoundException((NoHandlerFoundException) ex, headers, status, request);
    
    else if (ex instanceof AsyncRequestTimeoutException) 
        HttpStatus status = HttpStatus.SERVICE_UNAVAILABLE;
        return handleAsyncRequestTimeoutException(
                (AsyncRequestTimeoutException) ex, headers, status, request);
    
    else 
        if (logger.isWarnEnabled()) 
            logger.warn("Unknown exception type: " + ex.getClass().getName());
        
        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
        return handleExceptionInternal(ex, null, headers, status, request);
    
   

Entonces, la pregunta es: ¿cómo anular el controlador de excepciones para una excepción específica?
Este enfoque no puede funcionar:

@ExceptionHandler(value =  HttpRequestMethodNotSupportedException.class )
protected ResponseEntity handleConflict(HttpRequestMethodNotSupportedException ex, WebRequest request) 
   ...


Porque dentro de la clase del controlador de excepciones, Spring no le permite definir más de una vez un mapeo para un Exception subclase. Por lo tanto, no se permite agregar este mapeo en su controlador de excepciones personalizado porque Spring ya define un mapeo para esa excepción en el ResponseEntityExceptionHandler clase.
Concretamente, evitará que el contenedor Spring se inicie con éxito.
Debería obtener una excepción como:

Caused by: java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.HttpRequestMethodNotSupportedException]: {protected org.springframework...

Para facilitar que las subclases de clientes anulen el manejo / mapeo real para una excepción específica, Spring implementó la lógica de cada excepción capturada y manejada por sí misma en un protected método de El ResponseEntityExceptionHandler clase.
Entonces, en su caso (anulando el controlador de HttpRequestMethodNotSupportedException), solo anular handleHttpRequestMethodNotSupported() eso es lo que buscas:

if (ex instanceof HttpRequestMethodNotSupportedException) 
    HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
    return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);

Por ejemplo de esta manera:

@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler 

    @Override
    protected ResponseEntity handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status,
            WebRequest request)     
        // do your processing
         ...
        // go on (or no) executing the logic defined in the base class 
        return super.handleHttpRequestMethodNotSupported(ex, headers, status, request);
    


Recuerda que te damos el privilegio agregar una reseña si hallaste tu duda a tiempo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respuestas a preguntas comunes sobre programacion y tecnología