【问题标题】:How to collect all fields annotated with @RequestParam into one object如何将使用@RequestParam 注释的所有字段收集到一个对象中
【发布时间】:2019-10-21 10:51:24
【问题描述】:

我想将我的所有查询参数收集到一个 pojo 中并执行额外的字段验证。

我已经读到我可以简单地创建一个对象,spring-boot 会自动在其上设置这些请求参数。

@GetMaping public ResponseEntity<?> listEntities(@RequestParam(value = "page-number", defaultValue = "0") @Min(0) Integer pageNumber, @RequestParam(value = "page-size", defaultValue = "100") @Min(1) Integer pageSize ... )

我正在考虑创建一个名为 RequestParamsDTO 的类,我将在其中让我的查询参数负责分页。

但是为了在RequestParamsDTO 上设置这些字段,我必须将请求参数的名称与字段名称相匹配。但它不是有效的变量名:page-size

必须有一些解决方法,类似于@RequestParam 的 value 属性,可以在 DTO 中的我的字段上设置给定的请求参数。

请指教。

【问题讨论】:

  • 不确定这是否可行。试试@JsonProperty("page-size")
  • 为什么不在请求正文中将它们全部设置为json,然后使用POJO使用@RequestBody将其映射到控制器中
  • 因为在GET请求上提交payload不是rest-y,所以查询参数
  • 我试过@JsonProperty,不行
  • 我不敢相信它没有机制!

标签: spring-boot spring-mvc


【解决方案1】:

之前有人已经使用此feature,以便您可以执行以下操作。但不幸的是,由于不活动响应而被拒绝:

public class RequestParamsDTO{
   @RequestParam(value="page-number",defaultValue="0")
   @Min(0)
   private Integer pageNumber;

   @RequestParam(value = "page-size", defaultValue = "100") 
   @Min(1) 
   Integer pageSize 
}

您可以做的最相似的事情是使用它的@ModelAttribute,它将解析以下orders中的参数:

  • 如果已使用模型添加,则来自模型。
  • 使用 @SessionAttributes 从 HTTP 会话。
  • 来自通过转换器传递的 URI 路径变量(参见下一个示例)。
  • 来自默认构造函数的调用。
  • 通过调用带有与 Servlet 请求参数匹配的参数的“主构造函数”。参数名称通过 JavaBeans @ConstructorProperties 或字节码中运行时保留的参数名称确定。

这意味着RequestParamsDTO 不能没有任何默认构造函数(没有参数的构造函数)。它应该有一个“主构造函数”,您可以使用@ConstructorProperties 定义哪些请求参数映射到构造函数参数:

public class RequestParamsDTO{
    @Min(0)
    Integer pageNumber;
    @Min(1)
    Integer pageSize;

    @ConstructorProperties({"page-number","page-size"})
    public RequestParamsDTO(Integer pageNumber, Integer pageSize) {
        this.pageNumber = pageNumber != null ? pageNumber : 0;
        this.pageSize = pageSize != null ? pageSize : 100;
    }
}

而控制器方法变为:

@GetMaping
public ResponseEntity<?> listEntities(@Valid RequestParamsDTO request){

}

注意事项:

  • @RequestParamdefaultValue没有等效注解,需要在构造函数中手动实现。

  • 如果控制器方法参数与 this 中的值不匹配,它将解析为 @ModelAttribute,即使 @ModelAttribute 没有显式注释。

【讨论】:

  • 你自己试过了吗? @RequestParam 不允许在该字段上,它仅限于方法参数。github.com/spring-projects/spring-framework/blob/master/…
  • 我希望事情就这么简单。
  • 我会尝试@ConstructorProperties({"page-number","page-size"}) 并报告!
  • 我认为@ConstructorProperties 不会在这里工作:docs.oracle.com/javase/7/docs/api/java/beans/…
  • @IhorM。我已经向您展示了答案中的示例。我不使用@ModelAttribute 进行注释,因为我依赖于这样一个事实,即如果无法解析控制器方法参数,它将回退到@ModelAttribute。如果需要,您可以在控制器方法中的RequestParamsDTO 参数之前注释@ModelAttribute明确地做出来。另外,重要的一点是您必须确保RequestParamsDTO 不能有默认参数(即没有参数的构造函数)
【解决方案2】:

老实说,对于 spring-boot 中已经存在的功能,这似乎需要付出很多努力。您可以从 PagingAndSortingRepository 扩展您的存储库,并在调用集合资源时添加分页。

或者您可以编写自定义查询方法(或覆盖现有的)并添加:

Page<Person> findByFirstname(String firstname, Pageable pageable);

这样spring boot会自动将你想要的所有参数添加到Request中。

【讨论】:

  • 分页查询参数是作为示例给出的,不应按字面意思考虑。我有一堆要在 DTO 中分组的查询参数,然后根据它们的值执行验证。
猜你喜欢
  • 2022-12-15
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 2021-10-17
  • 1970-01-01
  • 2018-04-25
  • 2011-02-25
  • 1970-01-01
相关资源
最近更新 更多