如何从 Validated Spring RestController 获取多个缺失请求参数的详细信息?

Posted

技术标签:

【中文标题】如何从 Validated Spring RestController 获取多个缺失请求参数的详细信息?【英文标题】:How do I get the details of multiple missing request parameters from a Validated Spring RestController? 【发布时间】:2017-12-10 02:47:04 【问题描述】:

我正在尝试使用 Spring 对两个 @RequestParams 的验证,@ControllerAdvice 在缺少参数时捕获框架抛出的异常,并返回缺少参数的 400 错误。

所以,我的代码如下:

@RestController
@Validated
public class FooController 
  @RequestMapping(value = "/foo", method = RequestMethod.GET)
  @ResponseBody
  public Foo getFoo(@RequestParam LocalDate dateFrom, @RequestParam LocalDate dateTo) 
    // Do stuff
  


@ControllerAdvice
public class ExceptionController 
  @ExceptionHandler(value = MissingServletRequestParameterException.class)
  @ResponseStatus(value = HttpStatus.BAD_REQUEST)
  @ResponseBody
  public ErrorResponse handleMissingParameterException(MissingServletRequestParameterException ex) 
    return new ErrorResponse(ex.getMessage());
  

如果我错过了一个参数,这将非常有效 - 我会得到一个不错的 JSON 响应,如下所示:


  "reason": "Required LocalDate parameter 'dateFrom' is not present"

状态为 400。

但是,如果我错过了两个参数,我会得到与上面相同的错误响应 - 即它只报告第一个丢失的参数,如果我可以列出所有参数,我会更喜欢它。

查看异常的方法,它似乎只打算处理单个参数 - 它有方法 getParameterName()getParameterType() 以单数形式。

有什么方法可以让 Spring 在单个异常中报告所有验证错误以改善客户端的体验?

【问题讨论】:

我会尝试将它们设为可选并添加 javax.validator 注释 顺便说一句,您确定调用了完全相同的方法,或者在同一路径上可能有另一个方法与单个参数? 【参考方案1】:

而是引入一个带有验证注释的 POJO 过滤器

public class Filter 
    @NotNull
    private LocalDate dateFrom;
    @NotNull
    private LocalDate dateTo;

然后在控制器中使用它

public Foo getFoo(@Valid Filter filter) 
  // Do stuff

BindingResult 将提供所有验证错误

【讨论】:

【参考方案2】:

您可以设置@RequestParam(required = false),然后使用@NotNull

如果参数是null,则将抛出ConstraintViolationException。要处理它,只需声明一个 @ExceptionHandler 方法。检查下面的代码sn-p

@RestController
@Validated
public class FooController 
  @RequestMapping(value = "/foo", method = RequestMethod.GET)
  @ResponseBody
  public Foo getFoo(
      @RequestParam (required = false) 
      @NotNull(message = "Required LocalDate parameter dateFrom is not present") 
      LocalDate dateFrom,
      @RequestParam (required = false) 
      @NotNull(message = "Required LocalDate parameter dateTo is not present") 
      LocalDate dateTo) 
  ) 
    // Do stuff
  


@ControllerAdvice
public class ExceptionController 
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<List<ErrorResponseDTO>> exceptionHandler(ConstraintViolationException e) 
        List<ErrorResponseDTO> errors = new ArrayList<>(e.getConstraintViolations().size());
        e.getConstraintViolations().forEach(violation -> errors.add(new ErrorResponseDTO(violation.getMessage())));
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    

结果会是这样的:

[
    
        "reason": "Required LocalDate parameter dateFrom is not present"
    ,
    
        "reason": "Required LocalDate parameter dateTo is not present"
    
]

【讨论】:

以上是关于如何从 Validated Spring RestController 获取多个缺失请求参数的详细信息?的主要内容,如果未能解决你的问题,请参考以下文章

服务层中的Spring @Validated

Spring提供的@Validated和MethodValidationPostProcessor完成数据校验

@validated 验证 List 参数在spring中

Spring中@Valid和@Validated的区别

Spring boot @Validated注解以及配合@Valid的使用

spring参数校验@Validated及嵌套校验