hibernate validator

背景

我们在编写接口的时候、一定会有校验入参是否合法的需求,比如校验入参是否为空、是否为数字、是否是合法日期格式等等。此类需求如果使用代码去实现也不复杂、不过每个接口都去做重复工作就不是很合理,基于此,hibernate validator提供了一系列的注解,为我们完成这些工作

使用方式

1、 校验字符串不能为空

  • 在对象的属性中,添加@NotEmpty注解
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;
    }
}
  • 在接口中使用@Valid注解
	@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、校验日期必须在今天之前。方式同非空校验一样

  • 实体类中添加@Pass注解
	@Past
    private Date birthday;
  • 接口中添加@Valid注解
	@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 字符串必须是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执行查询等业务操作,最终返回用户名是否已经存在

  • 创建完注解之后、实际使用和hibernate validator默认注解使用并无二致
    @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);
    }

如此、用户名不可重复的校验就完成了

你可能感兴趣的:(工具)