ControllerAdvice 没有选择由作为 @RequestParam 传递的不正确 UUID 值抛出的 IllegalArgumentException

ControllerAdvice isn't picking IllegalArgumentException thrown by an incorrect UUID value passed as @RequestParam

我有以下控制器:

@Slf4j
@RestController
@RequestMapping("/v1")
@Validated
public class HighlightController {
    // ...
    @GetMapping("/highlights")
    public ResponseEntity<List<Highlight>> getHighlights(
            @RequestParam(required = false) UUID impersonateUserId
    ) {
      // ...

然后我有以下控制器异常处理程序:

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    //...

    @ExceptionHandler(value = IllegalArgumentException.class)
    public ResponseEntity<Object> handleIllegalArgumentException(IllegalArgumentException ex) {
        log.info("Handled: IllegalArgumentException", ex);
        return buildResponseEntity(new ApiErrorResponse(
                HttpStatus.BAD_REQUEST,
                "Incorrect Request",
                ex
        ));
    }

    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity<Object> handleRuntimeException(RuntimeException ex) {
        log.error("Handled: Runtime exception", ex);
        return buildResponseEntity(new ApiErrorResponse(
                HttpStatus.INTERNAL_SERVER_ERROR,
                "Internal error",
                ex
        ));
    }
 
    //...

    private ResponseEntity<Object> buildResponseEntity(ApiErrorResponse errorResponse) {
        return new ResponseEntity<>(errorResponse, errorResponse.getStatus());
    }

当我使用不正确的 UUID 值向 v1/highlights 端点发送请求时,我希望从字符串值解析 UUID 时 StringToUUIDConverter 抛出的 IllegalArgumentException 会被捕获handleIllegalArgumentException,而是由 handleRuntimeException 处理。这是为什么?

如果你调用你的控制器,例如:

http://localhost:8080/v1/highligths?impersonateUserId=x

结果会怎样?对我来说不是 IllegalArgumentException.

看看我得到了什么:

There was an unexpected error (type=Bad Request, status=400).
Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: Invalid UUID string: x org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: Invalid UUID string: x

难道你应该处理 MethodArgumentTypeMismatchException

我承认第一行暗示原因是 IllegalArguemntException

有点令人困惑

如果我打电话:

localhost:8080/v1/highligths?impersonateUserId=123e4567-e89b-12d3-a456-556642440000

似乎一切正常。

如果我再打电话:

http://localhost:8080/v1/highligths?impersonateUserId=123e4567-e89b-12d3-a456-556642440000x

我得到:

There was an unexpected error (type=Bad Request, status=400).
Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: UUID string too large org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: UUID string too large

但是,抛出的异常实际上是:

MethodArgumentTypeMismatchException