• @RequestParam 如何将参数绑定到对象上


    有这么一个场景,假设前台传递给我们三个参数 id、name、age ,我们很自然的会想到使用 @RequestParam 来接收前台传递过来的参数,具体示例如下

    @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 不支持直接传递实体类的方式,那么有其它的解决办法吗?

    答案是有的,具体示例如下

    @GetMapping("/getUserInfo")
    // 将请求参数中的 id、name、age 与实体类 saleman 进行绑定
    public String getUserInfo(Saleman saleman) {
        return saleman.toString();
    }
    

    很简单,只需要定义一个实体类就能完美解决,可是,如果要实现类似于 @RequestParam(required=true) 的校验该怎么办呢?

    其实也好办,我们可以在实体类里面进行校验

    @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 注解

    @GetMapping("/getUserInfo")
    // 要想实体类中的注解生效,必须要在实体类加上 @Valid 注解
    public String getUserInfo(@Valid Saleman saleman) {
        return saleman.toString();
    }
    

    这样,我们就模拟出了 @RequestParam(required=true) 的情形了,但是 @RequestParam 注解的作用还包括,如果未提供具体的参数,它会有默认值,这个该怎么实现呢?

    做法很简单,只需要在声明实体类属性的时候给一个默认值即可,类似 private Integer id = 2

    @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 注解的所有功能(空值校验、空值时的默认值)

    有时候根据业务需求,不会把所有的请求参数封装进同一个实体类中,我们可以将其封装进多个实体类中,具体的用法同上面一个实体类的相同

    @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

  • 相关阅读:
    Return Largest Numbers in Arrays
    Title Case a Sentence
    Find the Longest Word in a String
    Check for Palindromes
    Factorialize a Number
    Reverse a String
    nodejs使用场景
    居中div,居中浮动的元素
    WebSocket解释及如何兼容低版本浏览器
    HTML5的离线储存
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/15267799.html
Copyright © 2020-2023  润新知