如何在Spring中将@RequestParam绑定到对象

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

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

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

1. @RequestParams的列表太长

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

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

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

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

@RestController
@RequestMapping("/products")
class ProductController {//...@GetMappingList<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,因为他们根本不知道这是可能的。 @RequestParam的文档没有提到替代解决方案。

从更新控制器的方法开始,接受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 {@NotBlankprivate 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 {@NotNullprivate SortOrder order;@NotBlankprivate 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@Validprivate SortCriteria sort;// ...}

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

sort.order=ASC&sort.attribute=name

5.不变的DTO

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

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

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

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

@RequestParam

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

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

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

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

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

final class ProductCriteria {@NotBlankprivate 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请求的参数。 它应该像以前一样工作。

结论

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webstorm前端调用后端接口_软件测试面试题:怎么去判断一个bug是前端问题还是后端问题...

大家好&#xff0c;在软件测试面试过程中&#xff0c;经常有面试官问到这个问题&#xff0c;那我们应该如何回答才好呢&#xff1f;少废话&#xff0c;直接看答案&#xff1a;答案&#xff1a;在页面上发现bug之后&#xff0c;要想判断这个问题属于后端还是前端&#xff0c;我就…

首次适应算法_CVPR 2020丨?商汤TSD目标检测算法获得Open Images冠军

编者按&#xff1a;此前&#xff0c;在文章《商汤科技57篇论文入选ICCV 2019&#xff0c;13项竞赛夺冠》里&#xff0c;商汤君报道了商汤科技荣获Open Images Object Detection Challenge 2019 冠军。由Google AI主办的Open Images大赛是目前通用物体检测和实例分割两个领域中数…

玩JDK 12的Switch表达式

在博客文章“操作中的JDK语言功能预览&#xff1a;切换表达式 ”中&#xff0c;我讨论了JEP 325 [“切换表达式&#xff08; 预览 &#xff09;”&#xff09;如何作为指定的“ 预览语言功能 ”的早期应用&#xff0c;如JEP 12所述。预览语言和VM功能”]。 JEP 325 适用于JDK 1…

python 验证码_4行Python代码生成图像验证码

点击上方蓝色字体&#xff0c;关注我们最近无意看到网上有人使用Python编写几十行代码生成图像验证码&#xff0c;感觉很是繁琐&#xff0c;这里为各位朋友推荐两种方法&#xff0c;使用4行Python代码即可生成验证码。1captcha库第1步&#xff1a;安装captcha库pip install cap…

python3 多线程_Python3多线程爬虫实例讲解

多线程概述多线程使得程序内部可以分出多个线程来做多件事情&#xff0c;充分利用CPU空闲时间&#xff0c;提升处理效率。python提供了两个模块来实现多线程thread 和threading &#xff0c;thread 有一些缺点&#xff0c;在threading 得到了弥补。并且在Python3中废弃了thread…

java多条件组合查询6_elasticsearch组合多条件查询实现restful api以及java代码实现

elasticsearch组合多条件查询实现restful api以及java代码实现实际开发中&#xff0c;基本都是组合多条件查询。elasticsearch提供bool来实现这种需求&#xff1b;主要参数&#xff1a;must文档 必须 匹配这些条件才能被包含进来。must_not文档 必须不 匹配这些条件才能被包含进…

基于java家教管理系统_基于jsp的家教信息管理-JavaEE实现家教信息管理 - java项目源码...

基于jspservletpojomysql实现一个javaee/javaweb的家教信息管理, 该项目可用各类java课程设计大作业中, 家教信息管理的系统架构分为前后台两部分, 最终实现在线上进行家教信息管理各项功能,实现了诸如用户管理, 登录注册, 权限管理等功能, 并实现对各类家教信息管理相关的实体…

如何从云功能调用外部REST API

在之前的博客文章中&#xff0c;我展示了如何创建您的第一个云功能 &#xff08;以及一个视频 &#xff09;。 您的云函数很可能需要调用外部REST API。 以下教程将向您展示如何创建此类功能&#xff08;非常简单&#xff09;。 登录到IBM Cloud帐户 点击目录 删除标签&…

机器学习分类算法_机器学习分类算法

人们曾在自身的神经元得到启发&#xff0c;将机器学习中给出的特征输入与权重之积作为输出与阈值作比较&#xff0c;得到0或者1的输出。这就是我们感知器的实现原理感知器在实现过程中的步骤如下&#xff1a;①将权值初始化称为一个很小的向量②迭代训练所有样本&#xff1a;计…

apache camel_Apache Camel –从头开始开发应用程序(第1部分/第2部分)

apache camel开始之前 前段时间&#xff0c;我写了一篇关于Spring Integration的教程&#xff0c;以演示如何在受现实发票处理系统启发的示例应用程序中使用Spring Integration。 我对此非常满意&#xff0c;因此我决定向您展示如何使用Apache Camel&#xff08;Spring Integra…

weblogic创建域后启动不了_摩托车淋雨后启动不了什么原因?如何解决?

图文是工作&#xff0c;视频是生活。大家好&#xff0c;我是 骑士分享 欢迎您的关注&#xff01;摩托车淋雨后启动不了什么原因&#xff1f;如何解决&#xff1f;这种现象对于电喷车型来说发生的几率并不大&#xff0c;原因就在于电喷车型的线路防水能力会更强&#xff0c;供油…

前端开始学java_[Java教程]开启前端学习之路

[Java教程]开启前端学习之路0 2014-06-10 17:00:06前言第一次在博客园写博客&#xff0c;写写自己开启前端学习之路。应该是受邢师兄的影响吧&#xff0c;不得不说邢师兄人很好&#xff0c;学习也很认真&#xff0c;师兄的前端也是自学的&#xff0c;但是学的很好&#xff0c;大…

xalan_如何以10倍速加速Apache Xalan的XPath处理器

xalan一段时间以来&#xff0c; Apache Xalan中存在一个令人尴尬的错误&#xff0c;该错误是XALANJ-2540 。 此错误的后果是Xalan每次XPath表达式求值将内部SPI配置文件加载数千次 &#xff0c;可以很容易地进行如下测量&#xff1a; 这个&#xff1a; Element e (Element)do…

vim循环下表复制_Vimrc Init.vim太长了?不存在的

精简配置刚开始接触vim&#xff0c;你会被它各种好看的外观以及实用的插件吸引&#xff0c;各种折腾&#xff0c;不知不觉你的vimrc或者init.vim变得特别长&#xff0c;我之前的init.vim有多长&#xff1f;596行&#xff1f;wtf&#xff1f;每次维护的时候不知道有多麻烦&#…

visual studio odbc数据源设计器_NEW!WinForm界面开发设计时正式支持.NET 5

点击“了解更多”获取DevExpress v20.2完整版下载早在今年7月&#xff0c;官方技术团队宣布对DevExpress控件进行功能增强&#xff0c;使其支持最新的.NET 5 Preview。 但是尽管技术团队一直在努力确保WinForms控件与.NET 5兼容但在Visual Studio中对设计器的支持却是另一回事。…

java 接口的观察者模式_java观察者模式

观察者模式又叫做发布-订阅(Publish/Subscribe)模式。观察者模式定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时&#xff0c;会通知所有观察者对象&#xff0c;使它们能够自己更新自己。Observer结构图.pngSubj…

webgis从基础到开发实践_ArcGIS API For Javascript 开发笔记(四)

二、应用篇1、应用部署部署也就意味着一个 DEMO 或者系统即将完工&#xff0c;也意味着系统即将上线&#xff0c;相对来说Javascript 应用的部署不是很复杂&#xff0c;但是这是有前提的&#xff0c;要对部署中的一些概念有所了解&#xff0c;比如部署中常常提到的虚拟目录&…

Spock 1.2 –轻松进行集成测试中的Spring Bean模拟

探索如何使用Spock 1.2将Spock的模拟和间谍自动注入到Spring上下文中。 Spock中的存根/模拟/间谍&#xff08;及其生命周期&#xff09;一直与Spock Specification类紧密结合。 只能在测试类中创建它们。 因此&#xff0c;使用共享的预定义模拟&#xff08;在单元测试和集成测…

geteditor p 取消自动_2020百度网盘超级会员怎么取消自动续费?

首先我们打开百度网盘&#xff0c;开通超级会员以后&#xff0c;可以看到个人中心有一个管理自动续费的&#xff0c;点击打开。2然后可以看到自己开通的界面旁边显示的有一个取消按钮。3点击取消以后&#xff0c;会提示我们自动续费享受的有优惠&#xff0c;我们继续点击确认取…

分布式机器学习_229页,CMU博士张昊毕业论文公布,探索机器学习并行化的奥秘...

CMU 机器人研究所张昊&#xff08;Hao Zhang&#xff09;博士论文新鲜出炉&#xff0c;主要围绕着机器学习并行化的自适应、可组合与自动化问题展开。机器之心报道&#xff0c;机器之心编辑部。随着近年来&#xff0c;机器学习领域的创新不断加速&#xff0c;SysML 的研究者已经…