Hibernate Validator 校验 (一)

还想看更多文章的朋友可以访问我的个人博客


Hibernate Validator 校验 (简单校验)

Validator 规范对约束的定义包括两部分,一是约束注解, @NotBlank 就是约束注解;二是约束验证器,每一个约束注解都存在对应的约束验证器,约束验证器用来验证具体的对象是否满足该约束注解声明的条件。

声明需要校验的字段

User实体为例,其中username字段使用注解:@NotBlank,该注解声明username字段不能为空(虽该注解也要求字段不能为null,但与@NotNull有本质区别,后面会列举常见校验注解的区别)。


@Entity // This tells Hibernate to make a table out of this class
public class User {

    @NotBlank
    private String username;

    ...
}

测试用例,模拟发出增添用户的 Post 请求(username字段为"")。

@Test
public void testValidUser() throws Exception {
    String content = "{\"username\":\"\",\"password\": \"password\",\"birthday\":" + new Date().getTime() + "}";
    mockMvc.perform(post("/user").contentType(MediaType.APPLICATION_JSON_UTF8)
            .content(content))
            .andExpect(status().isOk());
}

执行后结果如下:


image

很明显,我们预想的校验并没有生效。那如何让我们添加的字段校验生效呢?

Mapping 方法参数声明需要校验的参数实例

Controller 层需要对传入参数添加@Valid注解,使得校验生效,如下:

@RestController
public class UserController {
  @PostMapping
  public User addUser(@RequestBody @Valid User user) {
      return userService.addUser(user);
    }
}

执行之前的测试用例,测试结果:


image

可以看出,我们执行形同的的测试用例,这次的测试请求却是失败的,也就是说我们对User实体中username字段的校验生效了。

但是,如果发生错误时我们只是向用户提醒请求错误时不够的。怎样才能自己处理想管的校验错误呢?

收集错误信息、发生错误时进入方法体。

只需要在Controller 层传入(注入)封装了错误信息的参数BandingResult类型的实例,如下修改Mapping方法:

@RestController
@RequestMapping("/user")
public class UserController {
  @Autowired
  private UserService userService;

  @PostMapping
  public User addUser(@RequestBody @Valid User user, BindingResult result) {
    // 输出错误信息
    if (result.hasErrors()) {
        result.getAllErrors().forEach(err -> System.out.println(err.getDefaultMessage()));
    }

    return userService.addUser(user);
  }
}

测试结果如下:

image

终于,模拟发出的用户添加请求返回的 HTTP 状态码为200,并且在Controller层也成功输出了错误信息:must not be blank

如此,借助 Hibernate Validator 支持的注解,即可为实体字段添加简单的校验,并在 Controller 层对校验的错误信息做相应处理(比如返回给前端)。

获得具体的校验错误信息

BindingResultgetAllErrors()方法返回值为List<ObjectError>,将ObjectError的实力强转为FieldError即可获得字段名称等信息。只需修改 Controller 层代码如下:

@RestController
@RequestMapping("/user")
public class UserController {
  @Autowired
  private UserService userService;

  @PostMapping
  public User addUser(@RequestBody @Valid User user, BindingResult result) {
      // 输出字段名称与校验错误信息
      if (result.hasErrors()) {
          result.getAllErrors().forEach(err -> {
              if (err instanceof FieldError) {
                  FieldError error = (FieldError) err;
                  System.out.println(error.getField() + " " + error.getDefaultMessage());
              }
          });
      }

      return userService.addUser(user);
  }
}

测试结果如下:


image

这样一来,就可以为前端提供较为具体的响应信息。

尽管如此,那如何为需要校验的校验项自定义错误消息呢?

自定义校验错误消息

其实,Hibernate Validator 提供的索引校验注解都有共同的一个属性——message,通过声明该属性,即可为校验项自定义错误消息,修改实体User校验字段@NotBlank注解如下:

@Entity
public class User {

    @NotBlank(message = "用户名不能为空")
    private String username;

    ...
}

Controller 层与测试用例无需修改,测试结果如下:


image

当然,此时很明显我们没有必要再输出字段名了,所以应该修改Controller层处的错误处理代码,但这里就不一一列举了。

Hibernate Validator 提供的校验注解

这里列举一些常用的 Hibernate Validator 提供的校验注解,利用这些注解可以完成开发中绝大多数的校验逻辑。

注解 描述
@NotNull 值不能为 null
@NotBlank 字符串必须包含字符
@NotEmpty 字符串不为 null,集合必须有元素
@Null 值必须为空
@Pattern(regex=) 字符串必须满足于正则
@Size(min=,max=) 集合的元素数必须在 min 到 max 之间
@CreditCardNumber(ignoreNonDightCharacters=) 字符串必须是信用卡号(美国标准如何自定义信用卡校验
@Email 字符串必须是Email
@Length(min=,max=) 校验字符串的长度
@Range(min=,max=) min <= 数字 <= max
@SafeHtml 字符串是安全的 HTML
@URL 字符串是合法的URL
@AssertFalse 布尔值为 false
@AssertTrue 布尔值为 true
@DecimalMax(value=,inclusive=) 值必须小于等于(inclusive=true)/小于(inclusive=false)指定的value值。可注解在字符串值上
@DecimalMin(value=,inclusive=) 值必须大于等于(inclusive=true)/大于(inclusive=false)指定的value值。可注解在字符串值上
@Digits(integer=,fraction=) 数字格式校验。integer指定整数部分长度,fraction指定小数部分长度
@Future 值必须是未来的日期
@Past 值必须是过去的日期
@Max 值必须小于等于value值。不可注解在字符串值上
@Min 值必须大于等于value值。不可注解在字符串值上
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,970评论 6 342
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong阅读 22,588评论 1 92
  • 空荡荡的教室里,除了灯光还有孤单的声音,不知哪里传来一阵悠扬的小号声,静静地听着,任时间像灰尘一样落下,覆盖了昨天...
    所为伊人阅读 195评论 0 0
  • 我想起了那个老人 好似是在路口单薄的身影 梦里的他 有着弯弯的背 那弯弯的背好似弯弯的桥 老人那褶皱中有双渴望的眼...
    何以至此阅读 217评论 0 1
  • 亲爱的家人们,晚上好!每天晚上记得汇报当日的功课完成情况啊。没有好坏对错,做功课也不是比赛,主要是我们一起养成活在...
    喜悦富足的小兔阅读 663评论 0 6