导入检验的包
<!-- 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
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";
}
}
```