Spring_数据校验和自定义检验规则和分组校验

@Validated  :绑定需要校验的数据.

数据校验规则:为数据绑定校验的规则

private Long booId;
@NotNull(message = "不能为空")
private String bookName;
private String author;
private String publisher;
@DecimalMin(value = "20",message = "不能低于20元")
@DecimalMax(value = "100",message = "不能多于100")
private Float price;
//正则表达式检验
//正则表达式用来判断某个字符串是否符合某个规则
//或者用来提取一整个字符 串中满足某个规则的子串
@Pattern(regexp = "1[345678][0-9]{9}")
private String Mobile;

为是实体类属性绑定检验规则:
message为检验不合格时的提示信息.
import javax.validation.constraints.*;

public class BookBean  {
    private Long booId;
    @NotNull(message = "书名不能为空")
    private String bookName;
    private String author;
    private String publisher;
    @DecimalMin(value = "20",message = "不能低于20元")
    @NotNull(message = "价格不能为空")
    @DecimalMax(value = "100",message = "不能多于100")
    private Float price;

    //正则表达式检验
    //正则表达式用来判断某个字符串是否符合某个规则
    //或者用来提取一整个字符 串中满足某个规则的子串
    @Pattern(regexp = "1[345678][0-9]{9}")
    private String Mobile;public String getIdCard() {
        return idCard;
    }

    public void setIdCard(String idCard) {
        this.idCard = idCard;
    }

    public String getMobile() {
        return Mobile;
    }

    public void setMobile(String mobile) {
        Mobile = mobile;
    }

    public Long getBooId() {
        return booId;
    }

    public void setBooId(Long booId) {
        this.booId = booId;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPublisher() {
        return publisher;
    }

    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }
}

绑定数据检验:

注意:校验结果:BindingResult  result必须经跟在@Validated BokBean bokBean 后面.用于接受检验的结果.

    @RequestMapping("/book/creat")
   public String create(@Validated BokBean bokBean, BindingResult result, Model model){

        //可以通过BindingResult对象拿到校验的错误信息.
        //注意:该参数必须要紧跟在被校验的对象的后面
        if (result.hasErrors()){
            //判断是否有检验的错误
//            result.getFieldError("bookName").getDefaultMessage();
            for (FieldError error : result.getFieldErrors()) {
                //获取被校验对象的所有错误
                String message = error.getDefaultMessage();
                System.out.println(message);
            }
            //可以直接把错误信息的集合都放到集合里
             model.addAttribute("erros", result.getFieldErrors());
            return "erro";
        }
        return "success";
   }

 

自定义检验规则,有时候spring自带的检验规则不满足我们使用时,可以自定义检验规则.

检验规则:

public class IDValidator implements ConstraintValidator<IDVlidation,String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //这里引用了一个身份证检验的工具类
        return IdCardUtils.isIDCard(value);
    }
    
//这个方法可不实现 @Override
public void initialize(IDVlidation constraintAnnotation) { } }

 

自定义一个检验规则的注解,自定义注解见自定义注解章节:https://www.cnblogs.com/zhouchangyang/p/10908343.html

定义这个注解为了方便,可仿造spring定义的注解规则写(赋值粘贴)

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })  //表明该注解可用在哪里
@Retention(RUNTIME)   //表明生效时间
@Repeatable(IDVlidation.List.class)
@Constraint(validatedBy = {IDValidator.class})  //注明该注解所实现的规则是哪个类
public @interface IDVlidation {

    String message() default "";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    @interface List {

        IDVlidation[] value();
    }

}

这样就定义好了一个规则的注解,

使用自定义注解和使用系统的注解一样,添加到需要校验的属性上面即可:

    @IDVlidation(message = "省份证不符合规范")
    private String idCard;

 

获取校验的后不满足规则的错误信息方式有两种:

一种就像上面一样在 方法参数中检验的对象后面添加 BindingResult result,

 @RequestMapping("/book/creat")
    public String create(@Validated BokBean bokBean, BindingResult result, Model model){

第二种是单独写一个获取错误信息的方法,在方法上添加注解,@ExceptionHandler(BindException.class),

通过 BindException ex  一样能获得第一种方法的BindingResult 对象.对错误信息的进一步操作和第一种方法一样.

    @ExceptionHandler(BindException.class)
    public String resolveBindinngExcrption(BindException ex){
        //获取错误结果集.
        BindingResult result = ex.getBindingResult();
        FieldError error = ex.getFieldError();
        System.out.println(result);
        return "erro";
    }

 

分组校验:

某些时候,我们前端的某些请求需要对某个对象的一部分属性进行校验,有一部分属性不需要校验.

这时我们就需要对校验的属性进行分组,根据前端的需求对属性进行分类.

比如登录和注册业务,他们引用的都是用户对象,但是登录只需要校验用户名和密码,而注册除了校验登录和注册还需要校验很多数据,

假如规定了注册时手机号不能为空,在登陆时不需要手机号,就会报错,这时就需要用分组来针对性的校验.

创建一个实体类,并对属性添加校验规则和分组信息,

public class UserBean  {

    //登录分组
    public interface LoginGroup{}
    //注册分组
    public interface RegisterGroup{}

    @NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
    private String username;
    @JsonIgnore  //表示不想序列化的数据
    @NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
    private String password;
    @Pattern(message = "手机号错误",regexp = "1[3-9][\\d]{9}",groups = {RegisterGroup.class})
    @NotNull(message = "手机号不能为空",groups = {RegisterGroup.class})
    private String mobile;
    @AssertTrue(groups = {RegisterGroup.class})
    private boolean agree;
    @JsonFormat(pattern = "yyyy-MM-dd-HH:mm:ss",timezone = "GMT+8")
    private Date birthday;

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    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;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public boolean isAgree() {
        return agree;
    }

    public void setAgree(boolean agree) {
        this.agree = agree;
    }
}

分组校验用法:

在实体类中创建内部接口类(可以是普通类),用来对业务进行分类,

public class UserBean  {

    //登录分组
    public interface LoginGroup{}
    //注册分组
    public interface RegisterGroup{}

在属性的检验规则中添加分组属性 : 

@NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
表示这个不能为空的检验规则登录和注册都需要满足.
   //登录分组
    public interface LoginGroup{}
    //注册分组
    public interface RegisterGroup{}

    @NotBlank(message = "不能为空",groups = {LoginGroup.class,RegisterGroup.class})
    private String username;
    @JsonIgnore  //表示不想序列化的数据
    @NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
    private String password;
    @Pattern(message = "手机号错误",regexp = "1[3-9][\\d]{9}",groups = {RegisterGroup.class})
    @NotNull(message = "手机号不能为空",groups = {RegisterGroup.class})
    private String mobile;
    @AssertTrue(message = "必须为真",groups = {RegisterGroup.class})
    private boolean agree;

规定好校验规则和分组后,只需在需要校验的地方使用就可以,

用法:在方法参数检验标记中添加分组属性:@Validated(UserBean.LoginGroup.class)

表示只有被UserBean.LoginGroup.class分组的校验规则才会被列入本次校验

@Controller
public class UserController {

    @RequestMapping("/login")
    public String login(@Validated(UserBean.LoginGroup.class) UserBean userBean){
        return "success";
    }

    @RequestMapping("/register")
    public String register(@Validated(UserBean.RegisterGroup.class) UserBean userBean){
        return "success";
    }

posted on 2019-05-23 21:09  周昌洋  阅读(830)  评论(0编辑  收藏  举报

导航