• 【Java】在实体类中常用的注解校验


    1、常用注解:

    注解说明
    @Null只能为null
    @NotNull(message = “id不能为空”)必须不为null,可以为空字符串
    @Min(value)必须为一个不小于指定值的数字
    @Max(value)必须为一个不大于指定值的数字
    @NotBlank(message = “姓名不能为空”)验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
    @NotEmpty验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
    @AssertFalse必须为false
    @AssertTrue必须为true
    @DecimalMax(value)必须为一个不大于指定值的数字
    @DecimalMin(value)必须为一个不小于指定值的数字
    @Digits(integer,fraction)必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
    @Future必须是一个将来的日期
    @Past必须是一个过去的日期
    @Pattern(regexp = “^(正则表达式)$”, message = “身份证格式错误”)必须符合指定的正则表达式
    @Size(max,min,message = “list大小不可为0”)字符长度必须在min到max之间
    @Length(min = 1,max = 4, message = “用户名不能超过4个字符”)被限制的字符串的大小必须在指定的范围内,一般用在 String 类型上可对字段数值进行最大长度限制的控制。
    @Email验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
    @Range(min = 60,max = 80,message = “年龄必须要60到80之间,60=<年龄=<80”)被注释的元素必须在合适的范围内,一般用在 Integer 类型上可对字段数值进行大小范围的控制。

    @NotEmpty、@NotBlank 以及 @NotNull 注解的使用:

    @NotEmpty 用在集合或数组上面,一般用来校验List类型(不能注释枚举),而且长度必须大于0
    @NotBlank 用在String上面,一般用来校验String类型不能为空,而且调用trim()后,长度必须大于0。
    @NotNull 用在所有类型上面,一般用来校验Integer类型不能为空,但可以为empty。
    需要搭配@Valid使用,在检验Controller的入参是否符合规范时

    @JsonFormat注解

    可以约束时间的接收格式和响应格式 (接收和响应的都是JSON字符串),将日期类型数据在JSON格式和java.util.Date对象之间转换 (前端传参是json字符串格式,后端返参也是json字符串格式,JsonFormat注解会自动转化成data格式进行处理)。与传输方向没有关系(前端到后端or后端到前端都可以使用)

    使用 @JsonFormat 注解时,查到的时间可能会比数据库中的时间少八个小时,这是由于时区差引起的,JsonFormat 默认的时区是 Greenwich Time, 默认的是格林威治时间,而我们是在东八区上,所以时间会比实际我们想得到的时间少八个小时。需要在后面加上一个时区,如下示例:

    @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
    private Date date;
    
    • 1
    • 2

    常用注解属性:

    名称作用
    pattern约定时间格式:pattern=“yyyy-MM-dd HH:mm:ss”
    timezone指定具体时区: timezone = “GMT+8” or timezone = “Asia/Shanghai”

    @DateTimeFormat注解:

    可对java.util.Date、java.uitl.calendar、java.long.Long及Joda时间类型的属性进行标注,主要处理前端时间类型与后端pojo对象中的成员变量进行数据绑定,所约束的时间格式并不会影响后端返回前端的时间类型数据格式(前端传参是json字符串格式,后端返参也是json字符串格式,DateTimeFormat注解会自动转化成data格式进行处理)

    注意:前端入参数据的时间格式必须与注解中定义的时间格式相同,不然会报错,如:@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm”) 则入参的格式必须为"2020-6-4 10:43";

    常用注解属性:

    名称作用
    iso类型为DateTimeFormat.ISO,常用值:DateTimeFormat.ISO.DATE:格式为yyyy-MM-ddDateTimeFormat.ISO.DATE_TIME:格式为yyyy-MM-dd hh:mm:ss.SSSZDateTimeFormat.ISO.TIME:格式为hh:mm:ss.SSSZDateTimeFormat.ISO.NONE:表示不使用ISO格式的时间(默认值)
    pattern类型为String,使用自定义时间格式化字符串,如"yyyy-MM-dd hh:mm:ss"
    style类型为String,通过样式指定日期时间的格式,由两位字符组成,第一位表示日期的样式,第二位表示时间的格式,以下是几个常用的可选值:S:短日期/时间的样式M:中日期/时间的样式L:短日期/时间的样式F:完整日期/时间的样子-:忽略日期或时间的样式默认值 style=“SS”

    @JsonFormat 和 @DateTimeFormat 区别

    @JsonFormat既可以约束前端传入的时间类型参数格式,也可以约束后端响应前端的时间类型格式;

    @DateTimeFormat :

    • 只能约束前端入参时间类型的格式,并不会修改原有的日期对象的格式,如果想要获得期望的日期格式,是需要自己手动转换的;
    • 如果单独使用@DateTimeFormat 时,响应给前端的时间会比实际时间晚8个小时(时区原因)

    参考链接:https://blog.csdn.net/zhuzicc/article/details/106529485

    @ApiModelProperty()注解:用于方法,字段; 表示对属性的说明或者数据操作更改

    value–字段说明
    name–重写属性名字 ,
    dataType–重写属性类型
    required–是否必填
    example–举例说明
    hidden–隐藏

    @ApiModel(value="user对象",description="用户对象user")
    public class User implements Serializable{
        private static final long serialVersionUID = 1L;
         @ApiModelProperty(value="用户名",name="username",example="xingguo")
         private String username;
         @ApiModelProperty(value="状态",name="state",required=true)
          private Integer state;
          private String password;
          private String nickName;
          private Integer isDeleted;
    
          @ApiModelProperty(value="id数组",hidden=true)
          private String[] ids;
          private List<String> idList;
         //省略get/set
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    一些校验注解的使用:

    在这里插入图片描述

    2、使用案例(@Valid注解的使用):

    @valid注解主要用于数据校验,可定义在两种地方。

    1. 定义实体类中的属性上,添加不同的注解来完成不同的校验规则。

    2. 定义在接口类中,在接收参数前添加@Valid注解,开启实体类的校验功能。

    1、在实体类中添加注解校验:

    public class OrderSync {
            private static final long serialVersionUID = 1L;
            /**
             * 用户Id
             */
            @ApiModelProperty(value = "用户id") //@ApiModelProperty是swagger的注解,它的作用是添加和操作属性模块的数据
            @NotEmpty(message = "用户id不能为空")
            private String userId;
            /**
             * 购买数量
             */
            @NotNull(message = "购买数量不能为空")
            private Integer quantity;
            /**
             * 支付时间
             */
            @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
            @NotEmpty(message = "支付时间不能为空")
            private LocalDateTime paymentTime;
        
            /**
             * 订单状态1、待发货 2、待收货 3、确认收货/已完成 5、已关闭
             */
            @Excel(name = "订单状态", readConverterExp = "1=待发货,2=待收货,3=确认收货/已完成 ,5=已关闭")
            @NotEmpty(message = "订单状态不能为空")
            private String orderStatus;
    
    }
    
    • 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

    2、在接口中添加@valid注解

    在controller类中添加接口,POST方法中接收设置了@Valid相关注解的实体对象,然后再参数中添加@Valid注解来开启效验功能,需要注意的是,@Valid对Get请求中接收的平面参数请求无效。

    @RestController
    public class TestController {
        @PostMapping("/sync")
        public String addUserInfo(@Valid @RequestBody OrderSync sync){
            return "调用成功";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    嵌套校验:

    为了能够进行嵌套验证,必须手动在Person实体的son字段上明确指出这个字段里面的实体也要进行验证。

    class Person {
        @NotNull
        private Integer id;
    
        @NotNull
        /**
         * @Validated不允许使用在成员属性上,所以只能用@Valid
         * 如果不加  @Valid 就不会对 Son类进行校验,只会判断 @NotNull,List是否为空,并不会Son类里面的成员属性
         */
        @Valid //嵌套验证
        private List<Son> son;
    }
    
    class Son {
        @NotNull
        private Integer sid;
    
        @NotBlank(message = "姓名不能为空")
        private String name;
    
    }
    
    class MemberController {
    
        @ApiOperation(value = "会员注册")
        @PostMapping("register")
                                  //使用@Validated或者@Valid都可以,这样就完成了嵌套验证
        public JSONResult register(@Validated @RequestBody Person person, BindingResult bindingResult){
    
            if (bindingResult.hasErrors()) {
                System.out.println(bindingResult.getFieldError().getDefaultMessage());
                return JSONResult.error().message(bindingResult.getFieldError().getDefaultMessage());
            }
            return JSONResult.ok();
        }
    
    }
    
    • 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
    • 37

    3、@Valid 与 @Validated注解的区别:

    @Valid、@Validated 注解可以实现数据的验证,你可以定义实体,在实体的属性上添加校验注解,如@NotEmpty,@NotBlank,@NotNull等等的注解就是,不加上就不会生效!
    @Valid 包位置:javax.validation
    @Validated 包位置 org.springframework.validation.annotation,是@Valid 的一次封装,是Spring提供的校验机制使用。

    不同点:

    1、使用位置:

    • @Validated:用在类型、方法和方法参数上。但不能用于成员属性(field)
    • @Valid:可以用在方法、构造函数、方法参数和成员属性(field)上
      在这里插入图片描述在这里插入图片描述

    如果@Validated注解在成员属性上,则会报 ‘@Validdated’ not applicable to field 错误:
    在这里插入图片描述

    2、分组上:@Valid 不支持分组, @Validated则支持分组验证。

    定义分组接口:

    public interface IGroupA {
    }
     
    public interface IGroupB {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    定义需要检验的参数bean:

    public class StudentBean implements Serializable{
        @NotBlank(message = "用户名不能为空")
        private String name;
        //只在分组为IGroupB的情况下进行验证
        @Min(value = 18, message = "年龄不能小于18岁", groups = {IGroupB.class})
        private Integer age;
        @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误")
        private String phoneNum;
        @Email(message = "邮箱格式错误")
        private String email;
        @MyConstraint
        private String className;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试代码:检验分组为IGroupA的情况,这里对分组IGroupB的就没检验了

    @RestController
    public class CheckController {
        @PostMapping("stu")
        public String addStu(@Validated({IGroupA.class}) @RequestBody StudentBean studentBean){
            return "add student success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果把测试代码改成下面这样,就会检验B了

    @RestController
    public class CheckController {
        @PostMapping("stu")
        public String addStu(@Validated({IGroupA.class, IGroupB.class}) @RequestBody StudentBean studentBean){
            return "add student success";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    说明:
    1、不分 配groups,默认每次都要进行验证
    2、对一个参数需要多种验证方式时,也可通过分配不同的组达到目的。

    相同点:

    在检验Controller的入参是否符合规范时,使用@Validated或者@Valid都可以实现,并且需要传入BindingResult对象,用于获取校验失败情况下的反馈信息,如下代码:

      @PostMapping("register")
                                 //@Valid这两个用哪个效果都一样
        public JSONResult register(@Validated @RequestBody RegisterVo registerVo, BindingResult bindingResult){
    
         //会把校验失败情况下的反馈信息
            if (bindingResult.hasErrors()) {
                System.out.println(bindingResult.getFieldError().getDefaultMessage());
                return JSONResult.error().message(bindingResult.getFieldError().getDefaultMessage());
            }
            memberService.register(registerVo);
            return JSONResult.ok();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总结:

    1.常用校验注解@NotEmpty,@NotBlank,@NotNull,需要搭配@Valid或@Validated使用

    2.@Valid或@Validated 中有 BindingResult,可以获取校验失败情况下的反馈信息,如果不添加,默认情况下会抛出对应的异常。

    3.@Validated无法单独提供嵌套验证功能。不能用在成员属性上,能配合嵌套验证注解@Valid进行嵌套验证。

    4.@Valid无法单独提供嵌套验证功能。能够用在成员属性上,能配合嵌套验证注解@Valid进行嵌套验证。

    参考链接:https://blog.csdn.net/weixin_46015018/article/details/122637042

  • 相关阅读:
    MySQL查询表结构方法
    Python初学:变量是什么?盘点那些变量的基本概念
    ELK日志分析系统叙述与部署,嘎嘎详细
    #php将时间戳 转化为天小时分秒#
    CS224W 5 Graph as Matrix: PageRank,Random Walks and Embeddings
    【图形学】28 更多的透明等式和参数
    并查集总结
    第一个Shader Graph
    基于SSM的校园二手物品交易市场设计与实现
    JS 封装节流(后期优化)
  • 原文地址:https://blog.csdn.net/m0_46459413/article/details/134301052