springboot-验证表单
什么是 hibernate-validator
hibernate-validator是springboot自带的一个数据验证器,需要引入外部依赖。
常见注解
注解 | 作用类型 | 说明 |
---|---|---|
@NotBlank(message=) | 字符串 | 要求元素为非null,且长度必须大于0 |
字符串 | 要求元素电子邮箱 | |
@Length(min=,max=) | 字符串 | 要求元素在指定范围内,min最小,max最大 |
@NotEmpty | 字符串 | 要求元素为非空 |
@NotEmptyPatter | 字符串 | 在字符串不为空的情况下,是否匹配正则表达式 |
@DateValidator | 字符串 | 验证日期格式,是否满足正则表达式 |
@DateFormatCheckPattern | 字符串 | 验证日期格式化,是否满足正则表达式,local为手动指定 |
@CreditCardNumber | 字符串 | 验证信用卡号码 |
@Range(min=,max=,message=) | 数值类型,字符串,字节 | 验证数据是否在合理范围内 |
@Null | 任意 | 要求元素必须为null |
@NotNull | 任意 | 要求元素必须不为null |
@AssertTrue | 布尔值 | 要求元素为true |
@Min(value) | 数字 | 要求元素必须为数字,且大于等于最小值 |
@Max(value) | 数字 | 要求元素必须为数字,且小于等于最大值 |
@DecimalMin(value) | 数字 | 要求元素必须为数字,且大于等于最小值 |
@DecimalMax(value) | 数字 | 要求元素必须为数字,且小于等于最大值 |
@Size(max,min) | 数字 | 要求元素在一个指定范围内,max最大,min最小 |
@Digits(integer,fraction) | 数字 | 要求元素必须是一个数字,且在可接受范围内 |
@Past | 日期 | 要求日期必须是一个过去的日期 |
@Future | 日期 | 要求日期必须是一个将来的日期 |
@Pattern(regex=,flag=) | 正则表达式 | 要求元素内容必须满足正则表达式规则 |
@ListStringPattern | List<String> | 要求集合中字符串内容满足正则表达式 |
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
写一个验证逻辑
package com.lu.model;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;
public class UserModel {
@NotBlank(message = "用户名不可为空")
@Length(min = 8,max = 32,message = "用户名在8-32位之间")
private String userName;
@NotNull(message="年龄不可为空")
@Range(min = 18, max = 120, message = "请填写合理的人类寿命范围")
private Integer userAge;
@NotBlank(message = "邮箱不可为空")
@Email(message = "请确保填入的是正确的邮箱地址")
private String userEmail;
@Past(message = "请确保,你出生在过去")
private Date userBirth;
public void setUserName(String userName) {
this.userName = userName;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public void setUserBirth(Date userBirth) {
this.userBirth = userBirth;
}
@Override
public String toString() {
return "UserModel{" +
"userName='" + userName + '\'' +
", userAge=" + userAge +
", userEmail='" + userEmail + '\'' +
", userBirth=" + userBirth +
'}';
}
}
package com.lu.controller;
import com.lu.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/register")
public class RegisterController {
@Autowired
private MessageSource messageSource;
@PostMapping("/validator")
// JSON请求格式数据校验
public String validator(@Valid @RequestBody UserModel userModel, BindingResult result) {
System.out.println(userModel);
StringBuilder builder = new StringBuilder();
// 没有错误则直接返回成功
if (!result.hasErrors()) {
return "pass: " + userModel.toString();
}
// 检查错误
for (ObjectError allError : result.getAllErrors()) {
// 获取当前语言的错误
String message = messageSource.getMessage(allError, LocaleContextHolder.getLocale());
builder.append(message).append('\n');
}
return builder.toString();
}
}
{
"userName":"jack",
"userAge":"-10",
}
邮箱不可为空
用户名在8-32位之间
请填写合理的人类寿命范围
具体实现过程如下
- 首先定义model
- 用注解约束model
- 编写controller
- @Valid 注解 标注model参数
- BindingResult 用来接受错误信息
- MessageSource 用来解析消息
自定义验证功能
虽然springboot的验证功能能满足绝大部分场景需求,但是如果要实现一些非常规验证,我们可以自定义规则。
流程
- 自定义注解
- @Constraint 标明验证器类
- 写一个验证器类 实现 ConstraintValidator接口
- 第一个参数:
自定义注解类型
- 第二个参数:
要验证的数据类型
- 第一个参数:
- 把自定义注解添加到要验证的字段上即可
自定义注解
package com.lu.annotations;
import com.lu.validator.ProvinceConstraintValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 作用在字段上
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ProvinceConstraintValidator.class)
public @interface ProvinceConstraint {
String message() default "请输入合法的城市名";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
需要注意的是,这里 Constraint注解标注对应验证器的类
编写验证器
package com.lu.validator;
import com.lu.annotations.ProvinceConstraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ProvinceConstraintValidator implements ConstraintValidator<ProvinceConstraint, String> {
@Override
public void initialize(ProvinceConstraint constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
return s.equals("山西省");
}
}
第一个参数是验证器注解,第二个参数是要验证的数据类型
使用自定义注解
package com.lu.model;
import com.lu.annotations.ProvinceConstraint;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;
public class UserModel {
@NotBlank(message = "用户名不可为空")
@Length(min = 8,max = 32,message = "用户名在8-32位之间")
private String userName;
@NotNull(message="年龄不可为空")
@Range(min = 18, max = 120, message = "请填写合理的人类寿命范围")
private Integer userAge;
@NotBlank(message = "邮箱不可为空")
@Email(message = "请确保填入的是正确的邮箱地址")
private String userEmail;
@Past(message = "请确保,你出生在过去")
private Date userBirth;
@ProvinceConstraint(message = "请输入合理的省份")
private String province;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public void setUserBirth(Date userBirth) {
this.userBirth = userBirth;
}
public String getUserName() {
return userName;
}
public Integer getUserAge() {
return userAge;
}
public String getUserEmail() {
return userEmail;
}
public Date getUserBirth() {
return userBirth;
}
@Override
public String toString() {
return "UserModel{" +
"userName='" + userName + '\'' +
", userAge=" + userAge +
", userEmail='" + userEmail + '\'' +
", userBirth=" + userBirth +
'}';
}
}
编写接口
实现 ConstraintValidator 接口
package com.lu.controller;
import com.lu.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.validation.Valid;
@RestController
@RequestMapping("/api/register")
public class RegisterController {
@Autowired
private MessageSource messageSource;
@PostMapping("/valid")
// JSON请求格式数据校验
public String validator(@Valid @RequestBody UserModel userModel, BindingResult result, RedirectAttributes attr) {
if (result.hasErrors()){
for (ObjectError allError : result.getAllErrors()) {
return allError.getDefaultMessage();
}
}
return "success";
}
}
测试接口
{
"userName":"luzhenfang",
"userEmail":"1223@qq.com",
"userAge":"22",
"province":"山西"
}
请输入合理的省份