说明
更新时间:2020/5/28 12:11,更新了list分组校验以及常用注解
更新时间:2020/5/27 23:23,更新了Hibernate Validator基本使用
本文主要记录本人在学习Hibernate Validator时的一些知识点,以便日后查看,本文会持续更新,不断地扩充
本文仅为记录学习轨迹,如有侵权,联系删除
一、Hibernate Validator简介
Hibernate Validator的出现是为了解决平时的项目开发中的数据正确性的校验问题,在平时开发中,为了确保数据的正确性,经常需要做数据的校验,传统的数据校验会显得代码冗长,而且不美观,而且如果项目较大的话,会出现很多重复代码。为了解决这个问题,Java中提供了Bean Validation的标准,该标准规定了校验的具体内容,通过简单的注解就能完成必要的校验逻辑了,相对来说就方便了很多,而该规范其实只是规范,并没有具体的实现,Hibernate提供了具体的实现,也即Hibernate Validator,这个也是目前使用得比较多的验证器了。
二、快速入门
入门案例
实体类
package com.zsc.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Father {
@Null(message = "主键不可以有值")
private Integer id;
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "年龄不能为空")
private Integer age;
}
Controller
package com.zsc.controller;
import com.zsc.po.Father;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.validation.Valid;
@Controller
public class FatherController {
@RequestMapping("/father")
public void father(@RequestBody @Valid Father father, BindingResult result){
//处理业务逻辑
if(result.hasErrors()){
for (ObjectError error : result.getAllErrors()) {
System.out.println(error.getDefaultMessage());
}
}
}
}
用Postman发起请求
控制台输出
可以看到后台确实有进行验证,同时也捕捉到了相应的异常,所以控制台会报错,然而将这些异常直接返回给前端是不行的,而且这里控制台还报错了就更别说了,所以,下面会对这些数据验证后产生的异常进行处理。
三、全局异常处理
在进行数据验证后,产生的异常需要经过处理后才能返回给前端
首先需要一个类(ResultVo),记录后端处理后的结果返回
package com.zsc.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.zsc.enums.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)//不为空的项才会加入序列化,表现为返回的信息中只返回不为null参数
public class ResultVo {
/**
* 后端是否处理成功
*/
private boolean success;
/**
* 返回状态码
*/
private String code;
/**
* 返回的处理后的信息
*/
private String msg;
/**
* 给前端的返回值
*/
private Object data;
/**
* 成功的返回
* @return
*/
public static ResultVo success(){
ResultVo resultVo = new ResultVo();
resultVo.setSuccess(true);
return resultVo;
}
/**
* 成功的返回
* @param data
* @return
*/
public static ResultVo success(Object data){
ResultVo resultVo = new ResultVo();
resultVo.setSuccess(true);
resultVo.setData(data);
return resultVo;
}
/**
* 失败的返回
* @param errorCode
* @return
*/
public static ResultVo fail(ErrorCode errorCode){
ResultVo resultVo = new ResultVo();
resultVo.setSuccess(false);
resultVo.setCode(errorCode.getCode());
resultVo.setMsg(errorCode.getMsg());
return resultVo;
}
/**
* 失败的返回
* @param errorCode
* @param data
* @return
*/
public static ResultVo fail(ErrorCode errorCode,Object data){
ResultVo resultVo = new ResultVo();
resultVo.setSuccess(false);
resultVo.setCode(errorCode.getCode());
resultVo.setMsg(errorCode.getMsg());
resultVo.setData(data);
return resultVo;
}
}
后端处理后,将结果通过ResultVo 类返回给前端,返回的时候需要设置错误状态码,错误信息等,为了方便查看状态码和状态码对应的错误信息,这里需要建一个枚举类(ErrorCode)存放这些状态码和状态码对应的错误信息
package com.zsc.enums;
public enum ErrorCode {
//这里简单的将参数状态码‘1000’错误信息设置为‘参数不正确’
PARAM_ERROR("1000","参数不正确");
//这里还可以设置其他状态码和对应的错误信息
private String code;
private String msg;
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
public void setCode(String code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
ErrorCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
}
现在需要创建一个类(CtrlAdvice )用来捕捉上面数据验证后的处理
package com.zsc.config;
import com.zsc.enums.ErrorCode;
import com.zsc.vo.ResultVo;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;
import java.util.stream.Collectors;
@ControllerAdvice(basePackages = "com.zsc.controller")//配置要捕捉的异常的包
@ResponseBody
public class CtrlAdvice {
//捕捉到异常后跳转到该方法
@ExceptionHandler
public ResultVo exceptionHandler(MethodArgumentNotValidException e){
/**
* MethodArgumentNotValidException:捕捉前端传上来的参数异常
* id - 主键不可以有值
* name - 名字不能为空
* birthday - 出生日期不能为空
* age - 年龄不能为空
* email - 邮件格式不正确
*/
/**
* 将异常的id(FieldError::getField)和值(getDefaultMessage)封装成一个map,返回给ResultVo
*/
Map<String, String> collect = e.getBindingResult().getFieldErrors().stream()
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
return ResultVo.fail(ErrorCode.PARAM_ERROR,collect);
}
}
配置好之后就可以进行真正的数据验证了
四、数据验证
控制层的校验
做完全局异常处理后,下面就可以进行真正的数据验证了,数据验证除了对基本数据类型的验证之外,还包括级联验证,即在一个类中存在自定义的数据类型,有一对一,一对多的情况,下面给出数据验证例子。
实体类User
package com.zsc.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.Date;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Null(message = "主键不可以有值")
private Integer id;
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "出生日期不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
@NotNull(message = "年龄不能为空")
private Integer age;
@NotBlank(message = "邮件不能为空")
@Email(message = "邮件格式不正确")
private String email;
//验证自定义实体类:一对一
@Valid
private Father father;
//验证自定义实体类列表:一对多
private List<@Valid Son> sons;
}
实体类Father
package com.zsc.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Father {
@Null(message = "主键不可以有值")
private Integer id;
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "年龄不能为空")
private Integer age;
}
实体类Son
package com.zsc.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Son {
@Null(message = "主键不可以有值")
private Integer id;
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "年龄不能为空")
private Integer age;
}
控制器UserController
package com.zsc.controller;
import com.zsc.po.User;
import com.zsc.vo.ResultVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@Validated//对本类中的方法开启参数验证功能
public class UserController {
@RequestMapping("/user")
public ResultVo user(@RequestBody @Valid User user){
//处理业务逻辑
return ResultVo.success();
}
}
下面进行测试
服务层的校验
服务层的校验,校验产生的异常就不是MethodArgumentNotValidException异常了,而是ConstraintViolationException异常,所以之前配置的异常捕捉就不会捕捉到ConstraintViolationException异常,需要在全局配置类CtrlAdvice 里面配置捕捉ConstraintViolationException的异常并做相应处理。
CtrlAdvice中新增服务层的异常捕捉
package com.zsc.config;
import com.zsc.enums.ErrorCode;
import com.zsc.vo.ResultVo;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.Map;
import java.util.stream.Collectors;
@ControllerAdvice(basePackages = "com.zsc.controller")//配置要捕捉的异常的包
@ResponseBody
public class CtrlAdvice {
//对应控制层的数据验证
//捕捉到MethodArgumentNotValidException异常后跳转到该方法
@ExceptionHandler
public ResultVo exceptionHandler(MethodArgumentNotValidException e){
/**
* MethodArgumentNotValidException:捕捉前端传上来的参数异常
* id - 主键不可以有值
* name - 名字不能为空
* birthday - 出生日期不能为空
* age - 年龄不能为空
* email - 邮件格式不正确
*/
/**
* 将异常的id(FieldError::getField)和值(getDefaultMessage)封装成一个map,返回给ResultVo
*/
Map<String, String> collect = e.getBindingResult().getFieldErrors().stream()
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
return ResultVo.fail(ErrorCode.PARAM_ERROR,collect);
}
//对应服务层的校验
//捕捉到ConstraintViolationException异常后跳转到该方法
@ExceptionHandler
public ResultVo exceptionHandler(ConstraintViolationException e){
Map<Path, String> collect = e.getConstraintViolations().stream()
.collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
return ResultVo.fail(ErrorCode.PARAM_ERROR,collect);
}
}
配置好服务层的异常捕捉后,设置服务层要校验的方法
服务层接口:UserService
package com.zsc.service;
import com.zsc.po.User;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public interface UserService {
void add(@Valid User user);//服务层的数据校验
//数据校验还可以这样校验
@NotNull User getById(@NotNull Integer id);
}
服务层接口实现类UserServiceImpl
package com.zsc.service.impl;
import com.zsc.po.User;
import com.zsc.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@Service
@Validated
public class UserServiceImpl implements UserService {
@Override
public void add(@Valid User user) {
//业务逻辑
System.out.println("数据添加成功");
}
@Override
public @NotNull User getById(@NotNull Integer id) {
return null;
}
}
控制层新增userService方法
package com.zsc.controller;
import com.zsc.po.User;
import com.zsc.service.UserService;
import com.zsc.vo.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@RestController
@Validated//对本类中的方法开启参数验证功能
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/user")
public ResultVo user(@RequestBody @Valid User user){
//处理业务逻辑
return ResultVo.success();
}
@RequestMapping("/userService")
public ResultVo userService(@RequestBody User user){
//处理业务逻辑
userService.add(user);
return ResultVo.success();
}
}
测试结果
分组校验
设想一下,User的主键id由于在进行数据的插入时,主键id一般由数据库默认自增,所以在前端发起插入数据时不需要传入id,所以上面图的id做了@Null验证,但是如果时数据更新的话,User的id就需要传给后端,但上面图的id却做了@Null验证,为了解决这个矛盾,就需要做分组校验,新修改的User如下图所示
实体类User
package com.zsc.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.util.Date;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
//分组校验:Update验证组和Add验证组
public interface Update{}
public interface Add{}
/**
* 如果指定了验证组,那么该参数就只属于指定的验证组
*
* 如果没有指定校验组,那么该参数就只属于默认组
*/
@Null(message = "插入数据时主键不可以有值",groups = {Add.class})
@NotNull(message ="更新时需要传主键id过来",groups = {Update.class})
private Integer id;
@NotBlank(message = "名字不能为空")
private String name;
@NotNull(message = "出生日期不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
@NotNull(message = "年龄不能为空")
private Integer age;
@NotBlank(message = "邮件不能为空")
@Email(message = "邮件格式不正确")
private String email;
//验证自定义实体类:一对一
@Valid
private Father father;
//验证自定义实体类列表:一对多
private List<@Valid Son> sons;
}
控制层
package com.zsc.controller;
import com.zsc.po.User;
import com.zsc.service.UserService;
import com.zsc.vo.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.groups.Default;
@RestController
@Validated//对本类中的方法开启参数验证功能
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/addUser")
public ResultVo add(@RequestBody @Validated({User.Add.class, Default.class}) User user) {
//增加用户时,数据校验就采用Add验证组和默认验证组
//处理业务逻辑
return ResultVo.success();
}
@RequestMapping("/updateUser")
public ResultVo update(@RequestBody @Validated({User.Update.class, Default.class}) User user) {
//更新用户时,数据校验就采用Update验证组和默认验证组
//处理业务逻辑
return ResultVo.success();
}
@RequestMapping("/userService")
public ResultVo userService(@RequestBody User user) {
//处理业务逻辑
userService.add(user);
return ResultVo.success();
}
}
测试插入数据(此时主键id校验不能有值)
测试更新数据(此时主键id需要传值过来)
自定义注解校验
一般Validator自带的注解校验足够应对正常的数据校验,但如果没有我们想要的数校验方式,可以自己定义一个注解进行自定义注解校验,假设现在要校验一个字段,如果该字段是Integer则要求该参数必须是偶数,如果是List则要求该参数的列表的个数(list.size()必须是偶数,可以自定义该注解。
在新建的包validator下的新建注解Even
package com.zsc.validator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 自定义注解校验
* 检验Integer字段是否为偶数
*/
@Documented//生成文档
@Target({ElementType.FIELD})//表示该注解作用于字段
@Retention(RetentionPolicy.RUNTIME)//表示在运行是依然生效
@Constraint(
validatedBy = {EvenForInteger.class,EvenForList.class}//添加实现类
)
public @interface Even {
String message() default "必须是偶数";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
注解对应的实现类EvenForInteger
package com.zsc.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class EvenForInteger implements ConstraintValidator<Even,Integer> {//表示作用于注解Even,要验证的类型为Integer
@Override
public void initialize(Even constraintAnnotation) {
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
//编写验证的逻辑
if(value == null){//如果null直接验证成功,null交给NotNull注解去验证
return true;
}
return value%2==0;
}
}
注解对应的实现类EvenForList
package com.zsc.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
public class EvenForList implements ConstraintValidator<Even, List> {//表示作用于注解Even,要验证的类型为List
@Override
public void initialize(Even constraintAnnotation) {
}
@Override
public boolean isValid(List value, ConstraintValidatorContext context) {
//编写验证的逻辑
if(value == null){//如果null直接验证成功,null交给NotNull注解去验证
return true;
}
return value.size() %2==0;//表示要验证的list的列表个数为偶数
}
}
做完就可以开始测试,这里在Father类上增加了两个字段用于测试注解Even
list中的分组校验
假设有一种场景如下
为此,需要定义一个注解用来校验上面的场景
自定义注解ValidList
package com.zsc.validation;
import com.zsc.validation.validator.ValidListValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.groups.Default;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 支持 list 中的分组校验
*/
@Target({FIELD,PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {ValidListValidator.class})
public @interface ValidList {
/**
* 要验证的分组
*/
Class<?>[] groupings() default {Default.class};
boolean quickFail() default false;//快速失败模式,一旦有校验失败的情况就不会再往下校验
String message() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
对应的实现类ValidListValidator
package com.zsc.validation.validator;
import com.zsc.config.ListValidException;
import com.zsc.utils.ValidatorUtils;
import com.zsc.validation.ValidList;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ValidListValidator implements ConstraintValidator<ValidList, List> {
Class<?>[] groupings;
boolean quickFail;
@Override
public void initialize(ValidList validList) {
groupings = validList.groupings();
quickFail = validList.quickFail();
}
@Override
public boolean isValid(List list, ConstraintValidatorContext context) {
Map<Integer, Set<ConstraintViolation<Object>>> errors = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
Object object = list.get(i);
Set<ConstraintViolation<Object>> error = ValidatorUtils.validator.validate(object, groupings);
if (error.size()>0) {
errors.put(i, error);
if (quickFail){
throw new ListValidException(errors);
}
}
}
if (errors.size()>0){
throw new ListValidException(errors);
}
return true;
}
}
因为需要用到底层的validator,所以需要写一个工具类ValidatorUtils将validator注入进来
package com.zsc.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.validation.Validator;
@Component
public class ValidatorUtils {
public static Validator validator;
@Autowired
public void setValidator(Validator validator) {
ValidatorUtils.validator = validator;
}
}
全局异常处理,需要在CtrlAdvice 新增异常捕获
package com.zsc.config;
import com.zsc.enums.ErrorCode;
import com.zsc.vo.ResultVo;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import javax.validation.ValidationException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
@ControllerAdvice(basePackages = "com.zsc.controller")//配置要捕捉的异常的包
@ResponseBody
public class CtrlAdvice {
//对应控制层的数据验证
//捕捉到MethodArgumentNotValidException异常后跳转到该方法
@ExceptionHandler
public ResultVo exceptionHandler(MethodArgumentNotValidException e){
/**
* MethodArgumentNotValidException:捕捉前端传上来的参数异常
* id - 主键不可以有值
* name - 名字不能为空
* birthday - 出生日期不能为空
* age - 年龄不能为空
* email - 邮件格式不正确
*/
/**
* 将异常的id(FieldError::getField)和值(getDefaultMessage)封装成一个map,返回给ResultVo
*/
Map<String, String> collect = e.getBindingResult().getFieldErrors().stream()
.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
return ResultVo.fail(ErrorCode.PARAM_ERROR,collect);
}
//对应服务层的校验
//捕捉到ConstraintViolationException异常后跳转到该方法
@ExceptionHandler
public ResultVo exceptionHandler(ConstraintViolationException e){
Map<Path, String> collect = e.getConstraintViolations().stream()
.collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
return ResultVo.fail(ErrorCode.PARAM_ERROR,collect);
}
@ExceptionHandler
public ResultVo exceptionHandler(ValidationException e){
Map<Integer, Map<Path, String>> map = new HashMap<>();
((ListValidException)e.getCause()).getErrors().forEach((integer, constraintViolations) -> {
map.put(integer, constraintViolations.stream()
.collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage)));
});
return ResultVo.fail(ErrorCode.PARAM_ERROR,map);
}
@ExceptionHandler
public ResultVo exceptionHandler(Exception e){
return ResultVo.fail(ErrorCode.SYSTEM_ERROR);
}
}
同时还需要一个异常类ListValidException
package com.zsc.config;
import javax.validation.ConstraintViolation;
import java.util.Map;
import java.util.Set;
public class ListValidException extends RuntimeException {
private Map<Integer, Set<ConstraintViolation<Object>>> errors;
public ListValidException(Map<Integer, Set<ConstraintViolation<Object>>> errors) {
this.errors = errors;
}
public Map<Integer, Set<ConstraintViolation<Object>>> getErrors() {
return errors;
}
public void setErrors(Map<Integer, Set<ConstraintViolation<Object>>> errors) {
this.errors = errors;
}
}
完成后开始进行测试,主要测试两种模式,快速结束模式和非快速结束模式
五、常用注解
给出Hibernate Validator常用注解,下面会详细讲到这些注解
@AssertTrue | 用于boolean字段,该字段只能为true |
@AssertFalse | 该字段的值只能为false |
@CreditCardNumber | 对信用卡号进行一个大致的验证 |
@DecimalMax | 只能小于或等于该值,字段或属性. 支持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
@DecimalMin | 只能大于或等于该值,字段或属性. 支持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
@Digits(integer=,fraction=) | 检查是否是一种数字的整数、分数,小数位数的数字,支持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
检查是否是一个有效的email地址,需要是String类型的. | |
@Future | 检查该字段的日期是否是属于将来的日期,支持类型是java.util.Date 和java.util.Calendar |
@Length(min=,max=) | 检查所属的字段的长度是否在min和max之间,只能用于字符串 |
@Max | 该字段的值只能小于或等于该值,持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
@Min | 该字段的值只能大于或等于该值,持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
@NotNull | 不能为null,支持所有类型 |
@NotBlank | 不能为空,检查时会将空格忽略,一般用于String |
@NotEmpty | 不能为空,这里的空是指空字符串,支持的类型包括String, Collection, Map 和数组. |
@Null | 检查该字段为空 |
@Past | 检查该字段的日期是在过去 |
@Pattern(regex=,flag=) | 被注释的元素必须符合指定的正则表达式,必须是String类型 |
@Range(min=,max=,message=) | 被注释的元素必须在合适的范围内 |
@Size(min=, max=) | 检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等 |
@URL(protocol=,host,port) | 检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件 |
@Valid | 该注解主要用于字段为一个包含其他对象的集合或map或数组的字段,或该字段直接为一个其他对象的引用,这样在检查当前对象的同时也会检查该字段所引用的对象 |
@Range(min=,max=) | min <= 数字 <= max,段或属性. 支持类型包括BigDecimal,BigInteger, String,byte, short, int, long和其各自对应的包装器类型. |
举例
转载:https://blog.csdn.net/qq_40298902/article/details/106376105