SpringMVC--数据校验,自定义校验注解,以及分组校验

导入检验的包


    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>6.0.16.Final</version>
    </dependency>

数据验证

创建书的校验

package com.lanou.demo.bean;

import com.lanou.demo.validator.IDValidations;

import javax.validation.constraints.*;


public class BookBean {

在book类中写校验注解

    private Long bookId;
    //校验书名不能为空
    @NotNull(message = "书名不能为空")
    private String bookName;
    private String author;
    private String publisher;
    //对书的单价校验不能是空,价格在20-100之间
    @DecimalMax(value = "100", message = "价格不超过100元")
    @DecimalMin(value = "20",message = "价格不低于20元")
    @NotNull
    private Float price;
    //设置身份正规范
    //这个注解是自定义的
    @IDValidations(message = "身份证不符和规范")
    private String idCard;
    /*
    正则表达式校验
    正则表达式用来判断某个字符串是否符合某个规则
    或者用来提取一整个字符串中满足某个规则的子串儿
    */
    //为手机号写正则表达式验证
    @Pattern(regexp = "1[345678][0-9]{9}",message = "手机号不符合规格")
    private  String mobile;


    public Long getBookId() {
        return bookId;
    }

    public void setBookId(Long bookId) {
        this.bookId = bookId;
    }

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

    public String getMobile() {
        return mobile;
    }

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

    public String getIdCard() {
        return idCard;
    }

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

自定义身份证注解

```package com.lanou.demo.validator;

import com.lanou.demo.untils.IdCardUtils;

import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.constraints.NotNull;
import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(IDValidations.List.class)
@Constraint(
validatedBy = {IDValidator.class}
)
public @interface IDValidations {

String message() default "身份证不符合规则";

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

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

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
    IDValidations[] value();
}

}

创建一个关于id工具类

package com.lanou.demo.untils;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

public class IdCardUtils {
final static Map<Integer, String> zoneNum = new HashMap<>();
static {
zoneNum.put(11, "北京");
zoneNum.put(12, "天津");
zoneNum.put(13, "河北");
zoneNum.put(14, "山西");
zoneNum.put(15, "内蒙古");
zoneNum.put(21, "辽宁");
zoneNum.put(22, "吉林");
zoneNum.put(23, "黑龙江");
zoneNum.put(31, "上海");
zoneNum.put(32, "江苏");
zoneNum.put(33, "浙江");
zoneNum.put(34, "安徽");
zoneNum.put(35, "福建");
zoneNum.put(36, "江西");
zoneNum.put(37, "山东");
zoneNum.put(41, "河南");
zoneNum.put(42, "湖北");
zoneNum.put(43, "湖南");
zoneNum.put(44, "广东");
zoneNum.put(45, "广西");
zoneNum.put(46, "海南");
zoneNum.put(50, "重庆");
zoneNum.put(51, "四川");
zoneNum.put(52, "贵州");
zoneNum.put(53, "云南");
zoneNum.put(54, "西藏");
zoneNum.put(61, "陕西");
zoneNum.put(62, "甘肃");
zoneNum.put(63, "青海");
zoneNum.put(64, "新疆");
zoneNum.put(71, "台湾");
zoneNum.put(81, "香港");
zoneNum.put(82, "澳门");
zoneNum.put(91, "外国");
}

final static int[] PARITYBIT = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
final static int[] POWER_LIST = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10,
        5, 8, 4, 2};

/**
 * 身份证验证
 *@param certNo  号码内容
 *@return 是否有效 null和"" 都是false
 */
public static boolean isIDCard(String certNo) {
    if (certNo == null || (certNo.length() != 15 && certNo.length() != 18))
        return false;
    final char[] cs = certNo.toUpperCase().toCharArray();
    //校验位数
    int power = 0;
    for (int i = 0; i < cs.length; i++) {
        if (i == cs.length - 1 && cs[i] == 'X')
            break;//最后一位可以 是X或x
        if (cs[i] < '0' || cs[i] > '9')
            return false;
        if (i < cs.length - 1) {
            power += (cs[i] - '0') * POWER_LIST[i];
        }
    }

    //校验区位码
    if (!zoneNum.containsKey(Integer.valueOf(certNo.substring(0, 2)))) {
        return false;
    }

    //校验年份
    String year = certNo.length() == 15 ? getIdcardCalendar() + certNo.substring(6, 8) : certNo.substring(6, 10);

    final int iyear = Integer.parseInt(year);
    if (iyear < 1900 || iyear > Calendar.getInstance().get(Calendar.YEAR))
        return false;//1900年的PASS,超过今年的PASS

    //校验月份
    String month = certNo.length() == 15 ? certNo.substring(8, 10) : certNo.substring(10, 12);
    final int imonth = Integer.parseInt(month);
    if (imonth < 1 || imonth > 12) {
        return false;
    }

    //校验天数
    String day = certNo.length() == 15 ? certNo.substring(10, 12) : certNo.substring(12, 14);
    final int iday = Integer.parseInt(day);
    if (iday < 1 || iday > 31)
        return false;

    //校验"校验码"
    return certNo.length() == 15 || cs[cs.length - 1] == PARITYBIT[power % 11];
}

private static int getIdcardCalendar() {
    GregorianCalendar curDay = new GregorianCalendar();
    int curYear = curDay.get(Calendar.YEAR);
    return Integer.parseInt(String.valueOf(curYear).substring(2));
}

}


实现自定义注解,

package com.lanou.demo.validator;

import com.lanou.demo.untils.IdCardUtils;
import org.springframework.validation.annotation.Validated;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

//继承ConstraintValidator(写写自定义注解,写要验证的值的类型)

public class IDValidator implements ConstraintValidator<IDValidations, String> {
@Override
public void initialize(IDValidations constraintAnnotation) {

}

@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
    return IdCardUtils.isIDCard(s);
}

}



在controller中写

@RequestMapping("/book/create")
//@Validated 数据校验
//加上之后就可以对属性进行校验
public String create(@Validated BookBean book,
BindingResult result,Model model){
//可以通过BindingResult的对象拿到校验信息.
//注意: 该参数必须紧跟着被检验对象的后面

   if(result.hasErrors()){
       //判断是否有校验错误
     //  result.getFieldError("bookName").getDefaultMessage();

       for (FieldError error : result.getFieldErrors()) {
           //获取校验对象的所有错误信息
           String message = error.getDefaultMessage();
       }
       //可以直接把错误信息的集合放到Model
       model.addAttribute("errors",result.getFieldErrors());
       return  "error";
   }
    return  "success";
}

在前端把book的错误信息显现出来

这是el表达式的方式
<%
List errors= (List ) request.getAttribute("errors");
for (FieldError error : errors) {
%>

<%= error.getDefaultMessage()%>


<%
}
%>

book验证完
----------------------------------------------------------------------------------------------------

分组验证



登录和注册的验证


创建一个类是做登录和注册的类

package com.lanou.demo.bean;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.util.Date;

public class UserBean {

//创建两个空的接口
//这两个接口是用来标记的
public interface LoginGroup{}
public interface RegisterGroup{}

//用户名在登录注册时都需要验证
@NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
private String username;

//密码也在在登录注册时都需要验证
@JsonIgnore
@NotBlank(groups = {LoginGroup.class,RegisterGroup.class})
@Length(min = 6,max = 20,groups = {LoginGroup.class,RegisterGroup.class})
private  String password;

//只在注册时验证
@Pattern(regexp = "1[3-9][\\d]{9}",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 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 Date getBirthday() {
    return birthday;
}

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

}

在controller中

package com.lanou.demo.controller;

import com.lanou.demo.bean.UserBean;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

//在登录时调用UserBean中的登录验证
@RequestMapping("/user/login")
public String login(@Validated(UserBean.LoginGroup.class) UserBean userBean){

    return "success";
}

//在注册时调用UserBean中的注册验证
@RequestMapping("/user/register")
public String register(@Validated(UserBean.RegisterGroup.class) UserBean userBean){

    return "success";
}


//通过异常处理捕获到异常
//捕获异常,在异常中处理异常,不用去判断
@ExceptionHandler(BindException.class)
public  String resolveBingingException(BindException ex){
   //通过异常对象获取到所有的验证错误
    FieldError fieldError = ex.getFieldError();

    return "error";
}

}

```

猜你喜欢

转载自www.cnblogs.com/lxx-1843693653/p/10925952.html