簡體   English   中英

如何使用@ExceptionHandler 捕獲 HTTP 405“Method Not Allowed”異常?

[英]How to catch HTTP 405 "Method Not Allowed" exception using @ExceptionHandler?

我創建了一個 REST 應用程序並添加了一個類來處理異常:

@RestControllerAdvice(basePackages = "com.foxminded.university.api.controller")
public class ApiGlobalExceptionHandler extends ResponseEntityExceptionHandler {
    private static final String API_UNHANDLED_EXCEPTION = "REST API reached unhandled exception: %s";
    private static final HttpStatus internalServerError = HttpStatus.INTERNAL_SERVER_ERROR;

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handle(Exception e) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, e.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()));
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }

    @Override
    public ResponseEntity<Object> handleTypeMismatch(
        TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, ex.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()));
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }

    @Override
    public ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers,
        HttpStatus status, WebRequest request) {
        ExceptionDetail exceptionDetail = new ExceptionDetail(
            String.format(API_UNHANDLED_EXCEPTION, e.getMessage()),
            internalServerError,
            ZonedDateTime.now(ZoneId.systemDefault()),
            e.getBindingResult().getFieldErrors());
        return new ResponseEntity<Object>(exceptionDetail, internalServerError);
    }
}

當我通過郵遞員發送錯誤的帖子請求時 http://localhost:8080/api/groups/jkjk 而不是 http://localhost:8080/api/groups

它向我拋出一個異常,我在調試時無法捕獲初始化,無論是在 ApiGlobalExceptionHandler 類中還是在 ResponseEntityExceptionHandler 類中:

{
    "timestamp": 1604171144423,
    "status": 405,
    "error": "Method Not Allowed",
    "message": "",
    "path": "/api/groups/jkjk"
}

我可以捕獲的所有其他異常。 如何捕獲此異常以添加自定義處理?

您只需要在其簽名中添加一個新方法 with MethodNotAllowedException

@ExceptionHandler(value = MethodNotAllowedException.class)
public ResponseEntity<Object> handleMethodNotAllowedExceptionException(MethodNotAllowedException ex) {
    return buildResponseEntity(HttpStatus.METHOD_NOT_ALLOWED, null, null, ex.getMessage(), null);
}

private ResponseEntity<Object> buildResponseEntity(HttpStatus status, HttpHeaders headers, Integer internalCode, String message, List<Object> errors) {
    ResponseBase response = new ResponseBase() //A generic ResponseBase class
            .success(false)
            .message(message)
            .resultCode(internalCode != null ? internalCode : status.value())
            .errors(errors != null
                    ? errors.stream().filter(Objects::nonNull).map(Objects::toString).collect(Collectors.toList())
                    : null);
    
    return new ResponseEntity<>((Object) response, headers, status);
}

您可以根據需要自定義buildResponseEntity

更新

我重新審視了我的答案,因為它不符合您的要求。 所以,它是這樣的:

我為接受GET的方法發送 post 請求。 這將觸發不支持的請求方法“POST” ,如下所示。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.Looking up handler method for path /v1/user/profile/1 org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.Resolving exception from handler [null]:org.springframework.web.HttpRequestMethodNotSupportedException:不支持請求方法“POST”

在這種情況下,不需要添加@ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)

事實上,如果你這樣做,會拋出以下錯誤(因為它已經被處理了),

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

因此,解決方案將是:

@Override
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request) {
    return buildResponseEntity(HttpStatus.METHOD_NOT_ALLOWED, headers, null, ex.getMessage(), Arrays.asList(""));
}

我在這里找到了解釋自定義處理 405 錯誤與 Spring Web MVC

它說The reason your @ExceptionHandler annotated method never catches your exception is because these ExceptionHandler annotated methods are invoked after a successful Spring controller handler mapping is found. However, your exception is raised before that. The reason your @ExceptionHandler annotated method never catches your exception is because these ExceptionHandler annotated methods are invoked after a successful Spring controller handler mapping is found. However, your exception is raised before that.

解決方案不是從 ResponseEntityExceptionHandler 類擴展,而是從 DefaultHandlerExceptionResolver 擴展並覆蓋它 handleHttpRequestMethodNotSupported 方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM