我们在编写接口的时候、一定会有校验入参是否合法的需求,比如校验入参是否为空、是否为数字、是否是合法日期格式等等。此类需求如果使用代码去实现也不复杂、不过每个接口都去做重复工作就不是很合理,基于此,hibernate validator提供了一系列的注解,为我们完成这些工作
1、 校验字符串不能为空
public class User {
private Integer id;
@NotEmpty
private String username;
@NotEmpty
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@PutMapping
public User addUser(@RequestBody @Valid User user, BindingResult errors, HttpServletResponse response) {
if (errors.hasErrors()) {
errors.getAllErrors().forEach(error -> System.out.println(((FieldError) error).getField() + "" + error.getDefaultMessage()));
response.setStatus(400);
return user;
}
return iUserService.addUser(user);
}
此时如果调用此接口的客户端、没有传username或password的值,那么请求会被hibernate validator拦截,并且将异常信息封装到BindingResult 对象中,我们在这里可以将异常信息封装到Exception类中返回至客户端。
2、校验日期必须在今天之前。方式同非空校验一样
@Past
private Date birthday;
@PutMapping
public User addUser(@RequestBody @Valid User user, BindingResult errors, HttpServletResponse response) {
if (errors.hasErrors()) {
errors.getAllErrors().forEach(error -> System.out.println(((FieldError) error).getField() + "" + error.getDefaultMessage()));
response.setStatus(400);
return user;
}
return iUserService.addUser(user);
}
以下为所有的支持的注解,使用方式并无二致
注解名称 | 解释 |
---|---|
@NotNull | 值不能为空 |
@Null | 值必须为空 |
@Pattern(regex=) | 字符串必须匹配正则表达式 |
@Size(min=, max=) | 集合的元素数量必须在min和max之间 |
@CreditCardNumber(ignoreNonDigitCharacters=) | 字符串必须是信用卡号(按照美国的标准校验!!) |
字符串必须是Email地址 | |
@Length(min=, max=) | 检查字符串的长度 |
@NotBlank | 字符串必须有字符 |
@NotEmpty | 字符串不为null,集合有元素 |
@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=) | 值必须小于等于value指定的值。不能注解在字符串类型的属性上 |
@Min(value=) | 值必须大于等于value指定的值。不能注解在字符串类型的属性上 |
在新增用户的时候、我们可能需要校验用户名是否重复,如果重复则提示更换用户名。这个也可以使用自定义validator注解实现
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@NotNull
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UserConstraintValidator.class)
public @interface UsernameNotRepeat {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@NotNull:代表被注解的字段不能为空
@Target({ElementType.METHOD, ElementType.FIELD}):此注解适用于方法和字段
@Retention(RetentionPolicy.RUNTIME):注解的生命周期,注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
@Constraint(validatedBy = UserConstraintValidator.class):实际业务执行类,在这里需要校验用户名是否重复
import com.mright.security.demo.platform.entity.User;
import com.mright.security.demo.platform.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class UserConstraintValidator implements ConstraintValidator<UsernameNotRepeat, String> {
@Autowired
private IUserService iUserService;
@Override
public void initialize(UsernameNotRepeat userConstraint) {
}
@Override
public boolean isValid(String username, ConstraintValidatorContext constraintValidatorContext) {
User user = iUserService.getUserByUsername(username);
return user == null;
}
}
此处必须实现ConstraintValidator接口,代表属于validator的子类,可用于注解校验。可以直接使用@Autowired注入我们的service执行查询等业务操作,最终返回用户名是否已经存在
@UsernameNotRepeat(message = "用户名已经存在")
private String username;
@PutMapping
public User addUser(@RequestBody @Valid User user, BindingResult errors, HttpServletResponse response) {
if (errors.hasErrors()) {
errors.getAllErrors().forEach(error -> System.out.println(((FieldError) error).getField() + "" + error.getDefaultMessage()));
response.setStatus(400);
return user;
}
return iUserService.addUser(user);
}
如此、用户名不可重复的校验就完成了