【问题标题】:Spring Boot - how to differentiate between validation for @PathVariable and query params (@RequestParam)Spring Boot - 如何区分@PathVariable 的验证和查询参数(@RequestParam)
【发布时间】:2021-06-04 01:03:09
【问题描述】:

如何对查询参数 (@RequestParam) 使用自定义验证/绑定?对于 @PathVariable 中的错误类型我想收到 404 错误,对于 @RequestParam 中的错误参数类型我想收到 400 或什么都没有。

我有@ControllerAdvice

@ExceptionHandler(value = {MethodArgumentTypeMismatchException.class})
    protected ResponseEntity handleException(NativeWebRequest request, MethodArgumentTypeMismatchException ex) {
        String error = ex.getName() + " in request URL should be of type " + ex.getRequiredType().getName();
        return create(HttpStatus.NOT_FOUND, error, ex);
    }

此异常处理程序捕获@PathVariable 上所有类型错误的情况。但是 - 如果query params 的类型错误,我不想抛出任何错误 - 我想在查询参数错误的情况下返回空列表,或者可能返回错误 400。

 @GetMapping("/v3/tw")
 public Page<TwDto> getTwByFilter(
            @RequestParam(name = "filter", defaultValue = "{}", required = false) @Valid TwSearchDto filter,
            @RequestParam(name = "sort", defaultValue = "{}", required = false) @Valid TwSortDto sort,
            @RequestParam(name = "page", defaultValue = "1", required = false) @Min(1) @ApiParam(value = "Minimum value: 1") int page,
            @RequestParam(name = "size", defaultValue = "10", required = false) @Min(1) @Max(100) @ApiParam(value = "Minimum value: 1\n\nMaximum value: 100") int size,
            Authentication authentication) {
        return twSearchService.getTwPage(filter, sort, page, size, authentication);
    }

如果出现无效参数,例如第 0 页,其中最小值为 1 @Min(1),我想返回错误代码 400(当前正在运行的行为)

目前在以下情况下:

 /api/rest/v2/tw?page=1string

返回错误代码 404(在调试模式下,我转到上面提到的 ExceptionHandler),但我不想抛出任何错误 404 - 相反,我想抛出错误代码 400。

如何在我的ControllerAdvice 中区分这两种情况?或者也许更好的是我不应该抛出任何错误而只返回空列表?

或者可能是另一个问题 - 如果异常来自@RequestParam,是否可以签入ExceptionHandler

【问题讨论】:

    标签: java spring-boot validation


    【解决方案1】:

    答案很简单——我们必须像这样从异常中获取正确的数据:

    HttpStatus status = ex.getParameter().getParameterAnnotation(PathVariable.class) != null ? HttpStatus.NOT_FOUND : HttpStatus.BAD_REQUEST;
    

    所以我的@ControllerAdvice中的这个exception handler负责处理和区分@PathVariable@RequestParam中错误类型引起的错误

    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class})
        protected ResponseEntity<Object> handleException(NativeWebRequest request, MethodArgumentTypeMismatchException ex) {
            String error;
            if (ex.getRequiredType() != null) {
                error = ex.getName() + " in request URL should be of type " + ex.getRequiredType().getName();
            } else {
                error = ex.getMessage();
            }
            HttpStatus status = ex.getParameter().getParameterAnnotation(PathVariable.class) != null ? HttpStatus.NOT_FOUND : HttpStatus.BAD_REQUEST;
            return create(status, error, ex);
        }
    

    并且此异常处理程序处理对象中的所有错误类型(端点有效负载):

     @Override
        @NonNull
        protected ResponseEntity<Object> handleHttpMessageNotReadable(@NonNull HttpMessageNotReadableException ex, @NonNull HttpHeaders headers, @NonNull HttpStatus status, @NonNull WebRequest request) {
            String message;
            if (ex.getCause() instanceof InvalidFormatException) {
                InvalidFormatException exception = (InvalidFormatException) ex.getCause();
                message = String.format("Cannot deserialize value of type %s from %s", exception.getTargetType(), exception.getValue());
            } else {
                message = ex.getMessage();
            }
            return create(HttpStatus.BAD_REQUEST, message, ex);
        }
    

    希望这个回答对你有帮助

    【讨论】:

      猜你喜欢
      • 2018-04-06
      • 1970-01-01
      • 2016-12-01
      • 2015-08-28
      • 2017-09-11
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 2020-02-11
      相关资源
      最近更新 更多