首页 > 其他分享 >Spring中将@RequestParam绑定到对象(转)

Spring中将@RequestParam绑定到对象(转)

时间:2024-04-22 16:33:55浏览次数:27  
标签:RequestParam int Spring 绑定 private 参数 POJO

译文:https://blog.csdn.net/dnc8371/article/details/106810876/

译文作者:dnc8371

来源:CSDN

原文:https://www.javacodegeeks.com/2018/10/how-bind-requestparam-object-spring.html

您是否在请求映射方法中用@RequestParam注释了多个参数,并认为它不可读?

当请求中需要一个或两个输入参数时,注释看起来非常简单,但是当列表变长时,您可能会感到不知所措。

您不能在对象内部使用@RequestParam批注,但这并不意味着您没有其他解决方案。 在本文中,我将向您展示如何用object替换多个@RequestParams 。

1. @RequestParams的列表太长

无论是控制器还是其他类,我都相信您同意很难读取一长串方法参数 。 另外,如果参数类型相同,则更容易出错。

诸如Checkstyle之类的静态代码分析工具可以检测方法中的大量输入,因为它被广泛认为是一种不好的做法。

通常,将一组参数一起传递到应用程序的不同层。 这样的组通常可以形成一个对象 ,您要做的就是提取它并给它起一个适当的名称 。

让我们看一下用于搜索某些产品的示例GET端点:

@RestController
@RequestMapping("/products")
class ProductController {
 
   //...
 
   @GetMapping
   List<Product> searchProducts(@RequestParam String query,
                                @RequestParam(required = false, defaultValue = "0") int offset,
                                @RequestParam(required = false, defaultValue = "10") int limit) {
       return productRepository.search(query, offset, limit);
   }
 
}

三个参数不是一个令人关注的数字,但它可以轻松增长。 例如,搜索通常包括排序顺序或一些其他过滤器。 在这种情况下,它们都被传递到数据访问层,因此它们似乎是参数对象提取的理想选择。

2. 将@RequestParam绑定到POJO

根本不用注解@RequestParams,如下,直接把POJO作为输入即可。

@GetMapping
List<Product> searchProducts(ProductCriteria productCriteria) {
   return productRepository.search(productCriteria);
}

POJO不需要任何其他注释。 它应具有与将与HTTP请求绑定的请求参数匹配的字段列表,标准的getter / setter和无参数的构造函数。

class ProductCriteria {
 
   private String query;
   private int offset;
   private int limit;
 
   ProductCriteria() {
   }
 
   public String getQuery() {
       return query;
   }
 
   public void setQuery(String query) {
       this.query = query;
   }
 
   // other getters/setters
 
}

验证POJO内部的请求参数

好的,但是我们不仅仅使用@RequestParam注释来绑定HTTP参数。 注释的另一个有用功能是可以根据需要标记给定参数。 如果请求中缺少参数,我们的端点可以拒绝它。

为了使用 POJO达到相同的效果(甚至更多!),我们可以使用bean验证 。 Java带有许多内置约束,但是如果需要,您总是创建一个自定义验证 。

让我们回到POJO并向字段添加一些验证规则。 如果只想模仿 @RequestParam(required = false) 的行为,则只需在必填字段上使用 @NotNull 批注 。

在许多情况下,使用@NotBlack代替@NotNull更有意义,因为它还涵盖了不需要的空字符串问题(长度为零的字符串)。

final class ProductCriteria {
 
   @NotBlank
   private String query;
   @Min(0)
   private int offset;
   @Min(1)
   private int limi;
 
   // ...
 
}

请注意:

添加字段的验证注释不足以使其起作用。

您还需要在控制器的方法中使用@Valid批注标记POJO参数。 这样,您通知Spring它应该在绑定步骤上执行验证。

@GetMapping
List<Product> searchProducts(@Valid ProductCriteria productCriteria) {
   // ...
}

POJO内部的默认请求参数值

@RequestParam批注的另一个有用的功能是能够在HTTP请求中未提供参数时定义默认值。

当我们拥有POJO时,不需要特殊的魔术。 您只需将默认值直接分配给字段。 当请求中缺少参数时,没有任何内容将覆盖预定义的值。

private int offset = 0;
private int limit = 10;

3. 多个对象

您没有被迫将所有HTTP参数放在单个对象中。 您可以在多个POJO中对参数进行分组。

为了说明这一点,让我们向端点添加排序条件。 首先,我们需要一个单独的对象。 就像之前一样,它具有一些验证约束。

final class SortCriteria {
 
   @NotNull
   private SortOrder order;
   @NotBlank
   private String sortAttribute;
 
   // constructor, getters/setters
 
}

在控制器中,只需将其添加为单独的输入参数即可。 请注意,@ Valid批注在每个应验证的参数上都是必需的。

@GetMapping
List<Product> searchProducts(@Valid ProductCriteria productCriteria, @Valid SortCriteria sortCriteria) {
   // ...
}

4. 嵌套对象

作为多个输入请求对象的替代,我们也可以使用组合。 参数绑定也适用于嵌套对象。

在下面,您可以找到一个示例,其中先前引入的排序条件已移至产品条件POJO。

要验证所有嵌套属性,应将@Valid批注添加到该字段。 请注意,如果该字段为null,Spring将不会验证其属性。 如果所有嵌套属性都是可选的,那可能是理想的解决方案。 如果不是,只需将@NotNull批注放在该嵌套对象字段上。

final class ProductCriteria {
 
   @NotNull
   @Valid
   private SortCriteria sort;
 
   // ...
 
}

HTTP参数必须使用点符号匹配字段名称。 在我们的情况下,它们应如下所示:

sort.order=ASC&sort.attribute=name

5. 不变的DTO

如今,您可以看到一种趋势,它倾向于使用不固定对象,而使用二传手来取代传统的POJO。

不可变的对象有很多好处(还有缺点……但是……)。 我认为,最大的一项是维护简单 。

您是否曾经在应用程序的数十个层中进行过跟踪,以了解哪些条件导致了对象的特定状态? 这个或那个字段在哪里改变了? 为什么要更新? setter方法的名称什么也没解释。 二传手没有任何意义。

考虑到创建Spring框架的事实,Spring强烈依赖POJO规范就不会让人感到惊讶。 然而,时代变了,旧的模式变成了反模式。

没有简单的方法可以使用参数化的构造函数将HTTP参数神奇地绑定到POJO。 非参数构造函数是不可避免的。 但是,我们可以将该构造函数设为私有 (但遗憾的是不能在嵌套对象中使用)并删除所有的setter。 从公众的角度来看,该对象将变得不可变。

默认情况下,Spring需要使用setter方法将HTTP参数绑定到字段。 幸运的是,可以重新配置绑定程序并使用直接字段访问(通过反射)。

为了为整个应用程序全局配置数据绑定器,您可以创建一个控制器建议组件。 您可以在以@InitBinder批注注释的方法内部更改绑定程序配置,该方法接受绑定程序作为输入。

@ControllerAdvice
class BindingControllerAdvice {
 
   @InitBinder
   public void initBinder(WebDataBinder binder) {
       binder.initDirectFieldAccess();
   }
 
}

创建该小类后,我们可以返回到POJO并从该类中删除所有setter方法,以使其变为只读状态以供公众使用。

final class ProductCriteria {
 
   @NotBlank
   private String query;
   @Min(0)
   private int offset = 0;
   @Min(1)
   private int limit = 10;
 
   private ProductCriteria() {
   }
 
   public String getQuery() {
       return query;
   }
 
   public int getOffset() {
       return offset;
   }
 
   public int getLimit() {
       return limit;
   }
 
}

重新启动您的应用程序,并使用HTTP请求的参数。 它应该像以前一样工作。

6. 结论

在本文中,您可以看到使用@RequestParam绑定在Spring MVC控制器中的HTTP请求参数可以轻松地替换为对多个属性进行分组的参数对象,仅不过是简单的POJO或可选的不可变DTO。

您可以在GitHub存储库中找到描述的样本 。 我希望所介绍的案例是不言自明的,但是如果有任何疑问或您想花两分钱,我强烈建议您将您的评论留在帖子下方。

翻译自: https://www.javacodegeeks.com/2018/10/how-bind-requestparam-object-spring.html

标签:RequestParam,int,Spring,绑定,private,参数,POJO
From: https://www.cnblogs.com/ajianbeyourself/p/18150877

相关文章

  • linux下springboot项目nohup日志或tomcat日志切割处理方案
    https://juejin.cn/post/7081890486453010469通常情况下,我们的springboot项目部署到linux服务器中,通过nohupjava-jarxxx.jar&指令来进行后台运行我们的springboot项目。这种方式针对中小型项目来说,还是比较简单方便的。通过nohup运行springboot项目,默认日志输出到当前目......
  • SpringBoot模块集成mqtt代码实现
    1//引入pom2<!--mqtt-->3<dependency>4<groupId>org.springframework.boot</groupId>5<artifactId>spring-boot-starter-integration</artifactId>6</dependency>......
  • springboot 嵌入式的web容器的的选择
    springboot默认内置tomcat可以替换undertow、jetty、nettytomcattomcat默认200最大线程完整实现了JEE容器和serlet规范tomcat6以后支持Jdk1.4的NIO用于完整支持了javaee因此比较笨重和重量级很多高并发会替换成undertowundertow这个是红帽2012开源出来的一个......
  • springwebFlux 版本对应关系
    springwebFlux是spring5、springboot2.4、springcloud2020webFlux采用响应式编程使用Rsocket协议代替HTTP使用场景主要在springcloudgateway、日志,监控检测等等springwebFlux和springmvc的相同点其实是一个升级版架构基本一致sprimgmvcServletRequest-》......
  • C#获取事件绑定的方法
    publicclassMyEventArgs{}publicdelegatevoidMyEventHandler(objectsender,MyEventArgsargs);publicclassMyControlClass:Control{publiceventMyEventHandlerMyEvent;publicDelegate[]GetEventDelegates(){if(MyEvent!=null)......
  • 【PLM踩坑记】新建SpringBoot项目,无法使用Java8
    概述今天开始学SpringBoot,需要使用IDEA新建SpringBoot项目。公司使用的Java版本为jdk1.8,这里我选择了这个版本的jdk之后,下面的Java选项不提供Java8。解决方法如下:首先将jdk版本选择为较新的jdk22,然后下面的Java版本随便选择一个。在正式进入项目之后,修改IDEA中的项目设置。点......
  • Spring Boot JPA
    SpringBootJPA是一个基于SpringBoot框架的Java持久层框架,它是JavaPersistenceAPI(JPA)的一个实现。JPA是Java平台上的一种ORM(对象关系映射)规范,它提供了一种简单、统一的方式来管理应用程序中的对象和关系型数据库之间的映射。SpringBootJPA基于Hibernate实现了......
  • springboot接口接收xml
    对xml文件的操作也可以借助hutool的XmlUtil.1.xml格式```xml<root> <deviceStatInfoonlineCount="64"offlineCount="2"errorCount="0"/> <data> <recordid="0"name="5号楼10层流量计"status="预警2/正常1......
  • SpringCloud进行nacos的服务注册和服务管理案例
    SpringCloud服务注册pom.xml<!--SpringCloud服务注册和发现--><dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.2.8.RELEASE</version>......
  • 【SpringBoot】【一】初识数据源连接池
    1 前言上节我们看了看,SpringBoot启动后都有哪些线程,看到有一部分是关于数据源连接池的,那么这节我们就看看数据源连接池都是如何工作的。我们本节就从这两个问题看起:(1)连接池是如何创建的,也就是什么时候创建的呢?(2)连接是什么时候放进连接池的?是创建完就初始化了一批新的连接,还......