@RequestParam 如何将参数绑定到对象上
有这么一个场景,假设前台传递给我们三个参数 id、name、age ,我们很自然的会想到使用 @RequestParam 来接收前台传递过来的参数,具体示例如下
1 2 3 4 5 6 7 8 9 10 11 | @GetMapping ( "/getUserInfo" ) public String getUserInfo( // 将前台传递过来的参数 id 对应的值绑定至 Integer 类型的参数 id // required 的默认值是 true,如果前台传递过来没有该参数,那么就会进行校验并报错 // 当 required = false 时,如果没有传递参数 id,那么它不会报错,而是使用默认值 10086 @RequestParam (value= "id" ,required = false ,defaultValue = "10086" ) Integer id, @RequestParam (value= "name" ,required = false ,defaultValue = "xiaomaomao" ) String name, @RequestParam (value = "age" ,required = false ,defaultValue = "21" ) Integer age) { return "id===" + id + " name===" + name + " age===" + age; } |
上面的示例看起来没有什么问题,可是实际上我们不难发现,如果前台传递过来的参数不是三个,而是十个,如果继续使用 @RequestParam 的方式来接收请求参数,就需要十个 @RequestParam ,我们的代码可读性将会变得很差,并且当参数类型相同时,十分容易出错,有没有什么好的解决方案呢?
这个时候可能你会想到使用实体类来接收传递过来的十个参数,想法是正确的,可是 @RequestParam 不支持直接传递实体类的方式,那么有其它的解决办法吗?
答案是有的,具体示例如下
1 2 3 4 5 | @GetMapping ( "/getUserInfo" ) // 将请求参数中的 id、name、age 与实体类 saleman 进行绑定 public String getUserInfo(Saleman saleman) { return saleman.toString(); } |
很简单,只需要定义一个实体类就能完美解决,可是,如果要实现类似于 @RequestParam(required=true) 的校验该怎么办呢?
其实也好办,我们可以在实体类里面进行校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Data public class Saleman { // id 最小值为 100 @Min ( 1 ) // id 不能为空,否则会报错 @NonNull private Integer id; // 如果是字符串类型的数据,使用 @NotBlank 比 @NoNull 更好,因为 @NotBlank 不仅会校验 null 值,它还会校验空字符串 @NotBlank private String name; // age 最大值为 30 @Max ( 30 ) // age 不能为空,否则校验不通过 @NonNull private Integer age; } |
注意你如果想要这些实体类中的注解生效,就必须要加上 @Valid 注解
1 2 3 4 5 | @GetMapping ( "/getUserInfo" ) // 要想实体类中的注解生效,必须要在实体类加上 @Valid 注解 public String getUserInfo( @Valid Saleman saleman) { return saleman.toString(); } |
这样,我们就模拟出了 @RequestParam(required=true) 的情形了,但是 @RequestParam 注解的作用还包括,如果未提供具体的参数,它会有默认值,这个该怎么实现呢?
做法很简单,只需要在声明实体类属性的时候给一个默认值即可,类似 private Integer id = 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @Data public class Saleman { // id 最小值为 100 @Min ( 1 ) // id 不能为空,否则会报错 @NonNull // 如果前台没有传递 id 参数,那么 id 会有默认值 2,注意这里的默认值一定要符合上面 @Min、@Nonnull 等注解的校验,否则该默认值设置的是不合理的 private Integer id = 2 ; // 如果是字符串类型的数据,使用 @NotBlank 比 @NoNull 更好,因为 @NotBlank 不仅会校验 null 值,它还会校验空字符串 @NotBlank private String name = "xiaomaomi" ; // age 最大值为 30 @Max ( 30 ) // age 不能为空,否则校验不通过 @NonNull private Integer age = 28 ; } @GetMapping ( "/getUserInfo" ) // 要想实体类中的注解生效,必须要在实体类加上 @Valid 注解 public String getUserInfo( @Valid Saleman saleman) { return saleman.toString(); } |
到此,我们就已经模拟出了 @RequestParam 注解的所有功能(空值校验、空值时的默认值)
有时候根据业务需求,不会把所有的请求参数封装进同一个实体类中,我们可以将其封装进多个实体类中,具体的用法同上面一个实体类的相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | @Data public class Saleman { // id 最小值为 100 @Min ( 1 ) // id 不能为空,否则会报错 @NonNull // 如果前台没有传递 id 参数,那么 id 会有默认值 2,注意这里的默认值一定要符合上面 @Min、@Nonnull 等注解的校验,否则该默认值设置的是不合理的 private Integer id = 2 ; // 如果是字符串类型的数据,使用 @NotBlank 比 @NoNull 更好,因为 @NotBlank 不仅会校验 null 值,它还会校验空字符串 @NotBlank private String name = "xiaomaomi" ; // age 最大值为 30 @Max ( 30 ) // age 不能为空,否则校验不通过 @NonNull private Integer age = 28 ; } @Data public class Product { @Min ( 100 ) @NonNull private Integer id = 10001 ; @NotBlank private String productName = "yishengwenhou" ; } @GetMapping ( "/getUserInfo" ) // 要想实体类中的注解生效,必须要在实体类加上 @Valid 注解 public String getUserInfo( @Valid Saleman saleman, @Valid Product product) { return saleman.toString() + "--------" + product.toString(); } |
但是有一个需要注意的地方,如果两个实体类中有相同的属性,那么前台传入的参数值会同时封装进入两个实体类中,例如前台传入一个 id,而 Saleman、Product 两个实体类都有 id 这个属性,那么 id 对应的参数值就同时封装进了 saleman、product
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2020-09-14 Mybatis动态SQL