Java 校验注解@NotNull,@NotBlank,@Max,@Valid等注解简单使用

た 入场券 2023-09-28 18:27 138阅读 0赞

说明

这些注解多用于进行参数校验,这里挑了几个简单使用下

首先创建一个项目

SpringBoot或者Maven项目都可以,我这里就选择Maven项目了

38750d3569d745778fc87b86072a7380.png

然后加入依赖

在pom里面添加依赖坐标

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-validation</artifactId>
  4. </dependency>

编写entity,controller代码

实体如下

这里我们分别对name限制不能为空,备注不能为空,这两个空是有区别的,age不能小于18岁,都是通过注解的方式去限制要求的

  1. package com.wyh.entity;
  2. import lombok.Data;
  3. import org.hibernate.validator.constraints.Length;
  4. import org.hibernate.validator.constraints.Range;
  5. import javax.validation.constraints.Max;
  6. import javax.validation.constraints.Min;
  7. import javax.validation.constraints.NotBlank;
  8. import javax.validation.constraints.NotNull;
  9. /**
  10. * @description: 用户实体表
  11. * @author: 魏一鹤
  12. * @createDate: 2022-08-03 22:09
  13. **/
  14. @Data
  15. public class User {
  16. @NotNull(message = "姓名不能为空!")
  17. private String name;
  18. @NotBlank(message = "备注不能为空!")
  19. private String remark;
  20. @Min(value = 18,message = "未满18岁不能注册!")
  21. private int age;
  22. }

controller如下

传统的判断应该是这样的,这样的话比较繁琐,判断较多的话且影响代码美观和读取

  1. if(name!=null){
  2. return "姓名不能为空!";
  3. }
  4. else if(age<18){
  5. return "未满18岁不能注册!";
  6. }

但是我们既然使用了注解 就要利用起来,使用如下优化的代码

  1. package com.wyh.controller;
  2. import com.wyh.entity.User;
  3. import org.springframework.validation.BindingResult;
  4. import org.springframework.web.bind.annotation.RequestBody;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import javax.validation.Valid;
  8. /**
  9. * @description: 用户中心控制器
  10. * @author: 魏一鹤
  11. * @createDate: 2022-08-03 22:12
  12. **/
  13. @RestController
  14. public class UserController {
  15. @RequestMapping("save1")
  16. /**
  17. * 有的朋友可能会问 @Valid和 BindingResult result是干嘛的
  18. * 1 @Valid 注解 表示我们对这个对象属性需要进行验证,
  19. * 2 BindingResult result:既然验证,那么就肯定会有验证结果,所以我们需要用一个东西来存放验证结果,做法也很简单,在参数直接添加一个BindingResult
  20. **/
  21. public Object test1(@Valid @RequestBody User user, BindingResult result){
  22. //判断有没有异常错误,如果有则返回默认消息
  23. //所有字段是否验证通过,true:数据验证有误,false:数据验证无误
  24. if (result.hasErrors()){
  25. // 如果数据验证有误,返回第一条错误信息到前端
  26. return result.getFieldError().getDefaultMessage();
  27. }
  28. return "注册成功";
  29. }
  30. }

这里着重说下

  1. @Valid BindingResult result是做什么的?
  2. 1 @Valid 注解 表示我们对这个对象属性需要进行验证
  3. 2 BindingResult result:既然验证,那么就肯定会有验证结果,所以我们需要用一个东西来存放验证结果,做法也很简单,在参数直接添加一个BindingResult

启动项目测试接口

打开你的接口测试工具进行测试,我这里使用的是apifox,接下来就是各种测试了

首先是一个正常添加的json

  1. {
  2. "name": "张三",
  3. "remark":"这是一份简介",
  4. "age": "20"
  5. }

fd07b4af9d6949d2b82beba847ead11b.png

然后测试name为空 直接舍弃这个字段

dd561c7e8be740349ee48b0515b5369b.png

还是测试name为空,这次加上name这个字段,但是值为空,发现成功了,说明@NotNull允许值为空,但是必须要有这个属性字段

5f7700ba112647e09e500c36d356b79e.png

接下来测试remark为空,可以发现,不管有没有remark这个字段,有没有值,@NotBlank都是过不了验证的

6db0bff439f54fd48dc2100cef9ff40f.png

502631a69e7a4f7582fcd798a990f8b0.png 然后测试age的值 少于18的值都会被拦截

a97cff4732504e5d8548f5a86922e38b.png

32d89fbd09f749098e602d01e95c5c35.png

那么问题来了,我当前有一个controller,需要在里面写异常捕获处理,没问题,但是如果业务比较多,难道每一个controller都要编写异常处理逻辑吗.那么肯定是不合适的,所以就要用全局异常类优化异常处理

编写全局异常类优化异常处理

创建一个新的controller用来做全局异常捕获

  1. package com.wyh.controller;
  2. import org.springframework.web.bind.MethodArgumentNotValidException;
  3. import org.springframework.web.bind.annotation.ControllerAdvice;
  4. import org.springframework.web.bind.annotation.ExceptionHandler;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. /**
  7. * @description: 全局捕获异常
  8. * @author: 魏一鹤
  9. * @createDate: 2022-08-03 22:45
  10. **/
  11. @ControllerAdvice
  12. public class ControllerException {
  13. private final static String EXCEPTION_MSG_KEY = "Exception message : ";
  14. @ResponseBody
  15. @ExceptionHandler(MethodArgumentNotValidException.class)
  16. public Object handleValidException(MethodArgumentNotValidException e) {
  17. //日志记录错误信息
  18. // log.error(Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
  19. //将错误信息返回给前台
  20. // return BaseResult.fail(500, Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
  21. return e.getBindingResult().getFieldError().getDefaultMessage();
  22. }
  23. }

为了区分方便测试,我们再写一个测试方法

  1. @RequestMapping("save2")
  2. public Object test2(@Valid @RequestBody User user){
  3. System.out.println(user);
  4. return "注册成功";
  5. }

还是一样的效果

3fb376df0b724a13ac7ca306bc494903.png

到此结束,我们再也不用写一堆各种判空逻辑处理了,使用这些注解的方式可以大大的提高我们的开发效率

多个的注解复杂使用

以上我们只是通过单个注释的方式去限制字段的值,我们多加几个玩一玩

首先修改实体,加的这几个属性大家应该也能看得懂,就不解释了

  1. @Data
  2. public class User {
  3. @NotNull(message = "姓名不能为空!")
  4. @Length(message ="名称不能超过{max}个字符",max = 5)
  5. private String name;
  6. @NotBlank(message = "备注不能为空!")
  7. private String remark;
  8. @Range(message = "年龄范围应该在{min}到{max}之间",min = 1,max = 100)
  9. private int age;
  10. }

重启测试接口

首先是名称大于5个字符

5acd5e405b7f4a36ac89611f4f1bd3d8.png

然后删除name,发现也通过不了,说明验证了可以多个注解去做处理的

458b3c5193e24a7aa2fce519840cf461.png

验证age的区间 不在1-100的直接pass

23e4f47728c74ee281c2ac6f0f19e1f2.png

正常的age

52b8d2f9924f47419e949e1ac6e5d7f5.png

常用部分注解

网上收集的,欢迎大家补充完善

@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

发表评论

表情:
评论列表 (有 0 条评论,138人围观)

还没有评论,来说两句吧...

相关阅读

    相关 使用注解校验前端传入数据

            后台接收前端传入的数据时,虽然前端会校验,但为了安全,我们后台也需要校验,这就造成了大量重复冗余的校验代码,看上去非常不优雅.         下面简单介绍注

    相关 java自定义校验注解

    随着业务的日趋复杂。我们对客户端传来的参数校验也越来越多。这么多的校验如果都写在业务逻辑中,业务代码看起来会很乱。 找时间学习了一下java的注解。特在此记录一下学习过程。