美文网首页SpringFramework
Hibernate Validator 校验 (一)

Hibernate Validator 校验 (一)

作者: 我是才子 | 来源:发表于2018-11-20 20:21 被阅读3次

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


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值。不可注解在字符串值上

相关文章

网友评论

    本文标题:Hibernate Validator 校验 (一)

    本文链接:https://www.haomeiwen.com/subject/hmffqqtx.html