后端校验注解一直在用,但是感觉不是特别清楚,希望通过写这篇文章搞清楚。
Spring提供了Validator接口来校验对象,主要涉及到的方法和类如下:
实体类
public class MyUser implements Serializable {
private String username;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
UserValidator
/**
* 用户数据校验类
*/
@Component
public class UserValidator implements Validator {
/**
* 对哪个类进行校验,此处仅对User类进行校验
* @param clazz
* @return
*/
@Override
public boolean supports(Class<?> clazz) {
return User.class.equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
//对name进行校验
ValidationUtils.rejectIfEmpty(errors, "username", "500", "name is empty");
MyUser user = (MyUser) target;
if (user.getAge() < 0) {
//
errors.rejectValue("age", "500", "年龄不能小于0");
}
}
}
Controller中的代码
@Autowired
private UserValidator userValidator;
@RequestMapping("/test3")
public void test1(MyUser user, Errors errors) {
userValidator.validate(user, errors);
if (errors.hasErrors()) {
//如果校验出错,输出错误信息
List<ObjectError> allErrors = errors.getAllErrors();
for (ObjectError error : allErrors) {
System.out.println("test1 error " + error.getCode() + " " + error.getDefaultMessage());
}
}
}
JSR 303是Java为Bean数据合法性校验提供的标准框架,已经包含在Java EE 6.0中。JSR是一个规范,它的核心接口是Validator,该接口根据目标对象类中所标注的校验注解进行数据校验,并得到校验结果。
JSR303包含的注解如下:
BindingResult:BindingResult扩展了Errors接口,同时可以获取数据绑定结果对象的信息。@Valid和BindingResult参数是成对出现的,并且在形参中出现的顺序是固定的,一前一后。
public class MyUser implements Serializable {
@NotNull(message = "username is empty")
@NotEmpty(message = "username is empty")
private String username;
@NotNull(message = "age is empty")
@Max(value = 150L, message = "年龄最大为150")
@Min(value = 0L, message = "年龄最小为0")
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
@RequestMapping("/test4")
public void test4(@Valid MyUser myUser, BindingResult result) {
if (result.hasErrors()) {
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError error : allErrors) {
System.out.println("error: " + error.getCode() + " " + error.getDefaultMessage());
}
}
}
JSR和Hibernate validator的校验只能对Object的属性进行校验,不能对单个的参数进行校验,spring 在此基础上进行了扩展,添加了MethodValidationPostProcessor拦截器,可以实现对方法参数的校验。
1、注入Bean
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
3、方法参数上加上注解校验
@RequestMapping("/test5")
public void test5(@NotNull(message = "username is empty") @NotEmpty(message = "username is empty")
@RequestParam String username, @NotNull(message = "age is empty") @Max(value = 150L, message = "年龄最大为150")
@Min(value = 0L, message = "年龄最小为0") @RequestParam Integer age) {
System.out.println("username: " + username + " age: " + age);
}
1、定义两个分组
public interface MyUserAddVo {
}
public interface MyUserUpdateVo {
}
2、指定分组,age属性的@NtoNull注解指定了MyUserAddVo.class, MyUserUpdateVo.class两个分组,而@Min指定了一个分组
public class MyUser implements Serializable {
@NotNull(groups = {MyUserAddVo.class, MyUserUpdateVo.class}, message = "username is empty")
@NotEmpty(groups = {MyUserAddVo.class, MyUserUpdateVo.class}, message = "username is empty")
private String username;
@NotNull(groups = {MyUserAddVo.class, MyUserUpdateVo.class}, message = "age is empty")
@Max(groups = {MyUserAddVo.class, MyUserUpdateVo.class}, value = 150L, message = "年龄最大为150")
@Min(groups = {MyUserAddVo.class}, value = 0L, message = "年龄最小为0")
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
}
3、在Controller中具体指定使用哪个分组的校验,代码中指定使用MyUserUpdateVo分组
/**
* 备注:此处@Validated(PersonAddView.class) 表示使用PersonAndView这套校验规则,若使用@Valid 则表示使用默认校验规则,
*若两个规则同时加上去,则只有第一套起作用
*
**/
@RequestMapping("/test6")
public void test6(@Validated({MyUserUpdateVo.class}) MyUser myUser) {
System.out.println("username: " + myUser.getUsername() + " age: " + myUser.getAge());
}
这两个注解都是进行数据校验的标志,区别如下: