前端验证一般是为了满足界面的友好性、客户体验性等,但仅靠前端进行数据合法性校验,是不够的。因为非法用户可能会直接从客户端获取请求地址进行非法请求,所以后端的校验是必不可少的。
在书写业务逻辑时,经常有大量的判空校验。比如Service层或Dao层的方法入参、入参对象、出参等都有一套校验规则。比如有的字段必传,有的非必传,返回值有些字段必须有值,有的非必须等等
众多if else的重复无意义代码,也可称为垃圾代码。Bean Validation校验是基于DDD思想设计的。
项目结构

├── java
│   └── com
│       └── whh
│           └── valid
│               ├── ValidApplication.java # 启动类
│               ├── annotation
│               │   └── Phone.java # 自定义验证注解
│               ├── config
│               │   └── ValidatorConfig.java # 表单验证配置类
│               ├── controller
│               │   └── SysUserController.java # 用户管理控制器
│               ├── exception
│               │   ├── BusinessException.java # 业务异常类
│               │   └── GlobalExceptionHandler.java # 统一异常处理类
│               ├── entity
│               │   ├── SysUser.java # 用户信息实体
│               │   └── ValidationInterface.java # 表单验证的通用分组接口
│               ├── util
│               │   └── CommonResult.java # 接口返回封装类
│               └── validation
│                   └── PhoneValidator.java #自定义验证实现类
└── resources
    ├── application.yaml # 配置文件
    └── messages
        └── validation
            └── messages.properties # 自定义验证信息源
导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.whh</groupId>
    <artifactId>valid</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>valid</name>
    <description>表单验证demo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!-- web支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 表单验证 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.3.5.Final</version>
        </dependency>
</dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
添加实体类
package com.whh.valid.enitty;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
@Data
public class SysUser {
    private static final long serialVersionUID = 1L;
    // 主键
    private Long id;
    //用户名
    @NotEmpty(message = "用户名不能为空")
    private String username;
    // 密码
    @Size(min = 6,max = 16,message = "密码长度必须在{min} - {max}之间")
    private String password = "123456";
    // 邮箱地址
    @Email(message = "邮箱地址不合法")
    @NotEmpty(message = "邮箱不能为空")
    private String email;
    // 电话
    @Size(min = 11,max = 11,message = "手机号不合法")
    @NotEmpty(message = "手机号不能为空")
    private String phone;
}
@Data注解:提高代码的简洁,使用这个注解可以省去代码中大量的get()、 set()、 toString()等方法;
接口返回封装类
package com.whh.valid.util;
import lombok.Data;
import lombok.NoArgsConstructor;
// 操作消息提醒
@Data
@NoArgsConstructor
public class CommonResult {
    // 状态码
    private int code;
    // 返回内容
    private String msg;
    // 数据对象
    private Object data;
    // 初始化一个CommonResult对象
    public CommonResult(Type type,String msg){
        this.code = type.value;
        this.msg = msg;
    }
    public CommonResult(Type type,String msg,Object data){
        this.code = type.value;
        this.msg = msg;
        if (data != null){
            this.data = data;
        }
    }
    // 返回成功消息
    public  static CommonResult success() {
        return CommonResult.success("操作成功");
    }
    public  static CommonResult success(Object data) {
        return CommonResult.success("操作成功",data);
    }
    public static CommonResult success(String msg) {
        return CommonResult.success(msg,null);
    }
    public static CommonResult success(String msg,Object data) {
        return new CommonResult(Type.SUCCESS,msg,data);
    }
    // 返回警告消息
    public static CommonResult warn(String msg) {
        return CommonResult.warn(msg,null);
    }
    public static CommonResult warn(String msg,Object data) {
        return new CommonResult(Type.WARN,msg,data);
    }
    // 返回错误消息
    public static CommonResult error(){
        return CommonResult.error("操作失败");
    }
    public static CommonResult error(String msg) {
        return CommonResult.error(msg,null);
    }
    public static CommonResult error(String msg,Object data) {
        return new CommonResult(Type.ERROR,msg,data);
    }
        public enum Type{
        // 成功
        SUCCESS(200),
        // 警告
        WARN(301),
        // 错误
        ERROR(500);
        private final int value;
        Type(int value){
            this.value = value;
        }
        public int getValue(){
            return this.value;
        }
    }
}
@NoArgsConstructor注解:注解在类上,为类提供一个无参的构造方法。
控制器
package com.whh.valid.controller;
import com.whh.valid.enitty.SysUser;
import com.whh.valid.util.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
@RestController
@RequestMapping("sys/user")
public class SysUserController {
    private static final List<SysUser> USERS = new ArrayList<>();
    // 数据初始化
    static {
        SysUser user = new SysUser();
        user.setId(1L);
        user.setUsername("wen");
        user.setPhone("13666666666");
        user.setEmail("example@qq.com");
        USERS.add(user);
        SysUser user1 = new SysUser();
        user1.setId(2L);
        user1.setUsername("li");
        user1.setPhone("13688888888");
        user1.setEmail("example1@qq.com");
        USERS.add(user1);
    }
    // 新增用户
    @PostMapping
    public CommonResult add(@Validated @RequestBody SysUser sysUser, BindingResult result) {
        FieldError fieldError = result.getFieldError();
        if (Objects.nonNull(fieldError)) {
            String field = fieldError.getField();
            Object rejectedValue = fieldError.getRejectedValue();
            String msg = "[" + fieldError.getDefaultMessage() + "]";
            log.error("{}: 字段=={}\t值={}",msg,field,rejectedValue);
            return CommonResult.error(msg);
        }
        USERS.add(sysUser);
        return CommonResult.success("新增成功");
    }
}
- @Validated注解:标识需要验证的类,使用BindingResult类接受错误信息
 - @Slf4j注解:用作日志输出的,一般会在项目每个类的开头加入该注解,如果不写下面这段代码,并且想用log
private final Logger logger = LoggerFactory.getLogger(当前类名.class); 
测试

log[邮箱地址不合法]: 字段==email    值=123
分组校验
groups表示注解属于哪个组,便按照哪个组的校验规则进行校验
当在controller中校验表单数据时,如果使用了groups,那么没有在这个分组下的属性是不会校验的
添加分组接口
package com.whh.valid.enitty;
// 用于表单验证的通用分组接口
public interface ValidationInterface {
    /**
     *新增分组
     */
    interface add{}
     /**
      * 删除分组
      */
    interface delete{}
    /**
     *查询分组
     */
    interface select{}
    /**
     * 更新分组
     */
    interface update{}
}
如果还有其它特殊的分组要求 直接在DO中创建interface即可
修改实体类
将属性进行分组
package com.whh.valid.enitty;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Data
public class SysUser {
    private static final long serialVersionUID = 1L;
    // 主键
    @NotNull(message = "id不能为空",groups = {ValidationInterface.update.class})
    private Long id;
    //用户名
    @NotEmpty(message = "用户名不能为空",groups = {
            ValidationInterface.update.class,
            ValidationInterface.add.class
    })
    private String username;
    // 密码
    @Size(min = 6,max = 16,message = "密码长度必须在{min} - {max}之间",groups = {
            ValidationInterface.update.class,
            ValidationInterface.add.class
    })
    private String password = "123456";
    // 邮箱地址
    @Email(message = "邮箱地址不合法",groups = {
            ValidationInterface.update.class,
            ValidationInterface.add.class,
            ValidationInterface.select.class
    })
    @NotEmpty(message = "邮箱不能为空",groups = ValidationInterface.add.class)
    private String email;
    // 电话
    @Size(min = 11,max = 11,message = "手机号不合法",groups = {
            ValidationInterface.update.class,
            ValidationInterface.add.class,
            ValidationInterface.select.class
    })
    @NotEmpty(message = "手机号不能为空",groups = {ValidationInterface.add.class})
    private String phone;
}
修改控制器
添加操作方法,并且方法形参上指定验证的分组
package com.whh.valid.controller;
import com.whh.valid.enitty.SysUser;
import com.whh.valid.enitty.ValidationInterface;
import com.whh.valid.util.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("sys/user")
public class SysUserController {
    private static final List<SysUser> USERS = new ArrayList<>();
    // 数据初始化
    static {
        SysUser user = new SysUser();
        user.setId(1L);
        user.setUsername("wen");
        user.setPhone("13666666666");
        user.setEmail("example@qq.com");
        USERS.add(user);
        SysUser user1 = new SysUser();
        user1.setId(2L);
        user1.setUsername("li");
        user1.setPhone("13688888888");
        user1.setEmail("example1@qq.com");
        USERS.add(user1);
    }
    /**
     * 根据手机号或邮箱查询用户信息
     * @param sysUser 用户信息
     * @param result 错误反馈
     * @return 用户信息
     */
    @GetMapping
    public CommonResult queryList(@Validated(value = ValidationInterface.select.class) SysUser sysUser,BindingResult result) {
        FieldError fieldError = result.getFieldError();
        if (Objects.nonNull(fieldError)) {
            return CommonResult.error(getErrorMsg(fieldError));
        }
        String phone = sysUser.getPhone();
        String email = sysUser.getEmail();
        if (phone == null && email == null){
            return CommonResult.success(USERS);
        }
        List<SysUser> queryResult = USERS.stream()
                .filter(obj -> obj.getPhone().equals(phone) || obj.getEmail().equals(email))
                .collect(Collectors.toList());
        return CommonResult.success(queryResult);
    }
    /**
     * 获取表单验证错误msg
     * @param fieldError 报错字段
     * @return msg
     */
    public String getErrorMsg(FieldError fieldError) {
        String field = fieldError.getField();
        Object rejectedValue = fieldError.getRejectedValue();
        String msg = "[" + fieldError.getDefaultMessage() + "]";
        log.error("{}: 字段=={}\t值=={}",msg,field,rejectedValue);
        return msg;
    }
    /**
     * 新增用户信息
     * @param sysUser 用户信息
     * @param result 错误反馈
     * @return 成功标识
     */
    @PostMapping
    public CommonResult add(@Validated(value = ValidationInterface.add.class)
                                @RequestBody SysUser sysUser,
                                BindingResult result) {
        FieldError fieldError = result.getFieldError();
        if (Objects.nonNull(fieldError)) {
            return CommonResult.error(getErrorMsg(fieldError));
        }
        Long id = (long)(USERS.size() + 1);
        sysUser.setId(id);
        USERS.add(sysUser);
        return CommonResult.success("新增成功");
    }
    /**
     * 根据id更新用户信息
     * @param id id
     * @param sysUser 用户信息
     * @param result 错误反馈
     * @return 成功标识
     */
    @PutMapping("{id}")
    public CommonResult updateByid(@PathVariable("id") Long id,
                                    @Validated(value = ValidationInterface.update.class)
                                    @RequestBody SysUser sysUser,
                                    BindingResult result) {
        FieldError fieldError = result.getFieldError();
        if (Objects.nonNull(fieldError)) {
            return CommonResult.error(getErrorMsg(fieldError));
        }
        for (int i=0;i<USERS.size();i++){
            if (USERS.get(i).getId().equals(id)) {
                USERS.set(i,sysUser);
            }
        }
        return CommonResult.success("更新成功");
    }
    /**
     * 根据Id删除用户信息
     * @param id id
     * @return 成功标识
     */
    @DeleteMapping("{id}")
    public CommonResult deleteByid(@PathVariable Long id) {
        USERS.removeIf(obj -> obj.getId().equals(id));
        return CommonResult.success("删除成功");
    }
}
测试
查询:输入不合法手机号
新增
去掉邮箱
更新:去掉id
删除
自定义验证
很多时候框架提供的功能并不能满足业务场景,需要自定义一些验证规则来完成验证。
添加注解
package com.whh.valid.annotation;
import com.whh.valid.validation.PhoneValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Constraint(validatedBy = {PhoneValidator.class})
@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE})
@Retention(RUNTIME)
public @interface Phone {
    // 默认错误消息
    String message() default "不是一个合法的手机号";
    // 分组
    Class<?>[] groups() default {};
    // 载荷 将某些 元数据信息与给定的注解声明相关联的方法
    Class<? extends Payload>[] payload() default {};
    //指定多个时使用
    @Target({FIELD,METHOD,PARAMETER,ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List{
        Phone[] value();
    }
}
- @Documented:是否将注解信息添加在Java文档中
 - @Retention:定义该注解的生命周期.(SOURCE:在编译阶段丢弃。这些注解在编译结束之后就不再有意义。例如@Override,@SuppressWarnings;CLASS:在类加载阶段丢弃,在字节码文件的处理中有用。注解默认使用这种方式;RUNTIME:始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解信息,自定义注解通常使用这种方式)
 - @Target:注解用于什么地方,如果不明确指出,该注解可以放在任何地方。属性的注解是兼容的。(TYPE:用于描述类、接口或enum声明;FIELD:用于描述实例变量;METHOD:用于描述方法;PARAMETER:参数;CONSTRUCTOR:构造方法;LOCAL_VARIABLE:局部变量;ANNOTATION_TYPE:另一个注释;PACKAGE:用于记录java文件的package信息)
 - @Constraint:处理注解的逻辑
 
编写验证逻辑
package com.whh.valid.validation;
import com.whh.valid.annotation.Phone;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Objects;
import java.util.regex.Pattern;
/**
 * 手机号校验器
 */
public class PhoneValidator implements ConstraintValidator<Phone,String> {
    /**
     * 手机号正则表达式
     */
    private static final String REGEXP_PHONE = "^1[3456789]\\d{9}$";
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (Objects.isNull(s)){
            return true;
        }
        return Pattern.matches(REGEXP_PHONE,s);
    }
}
修改实体
给phone添加注解@Phone
@Phone(groups = {
                ValidationInterface.update.class,
                ValidationInterface.add.class,
                ValidationInterface.select.class})
@NotEmpty(message = "手机号不能为空", groups = {ValidationInterface.add.class})
private String phone;
测试
输入错误的手机号测试
@Pattern
validation也提供了基于正则匹配的注解@Pattern
@Pattern(message = "手机号不合法",regexp = "^1[3456789]\\d{9}"$,groups = {ValidationInterface.add.class})
@NotEmpty(message = "手机号不能为空", groups = {ValidationInterface.add.class})
private String phone;
调用过程验证
有时候在参数传输过程中需要对传入的对象做参数验证,但是上面介绍的是对参数绑定时的验证。
使用 spring bean
- 注入validator
bean validator是在config中定义的bean,如果使用spring boot默认配置ValidationAutoConfiguration::defaultValidator(),直接注入bean@Resource(name = "validator") javax.validation.Validator validator; 
方法参数验证
- 修改控制器
直接在类上添加注解@Validated,并在方法上直接进行验证@Slf4j @Validated @RestController @RequestMapping("sys/user") public class SysUserController { ... 省略代码 /** * 根据手机号和邮箱查询用户信息 * @param phone 手机号 * @return 用户list */ @GetMapping("selectByPhone") public CommonResult queryByPhone(@NotEmpty(message = "手机号不能为空") String phone) { List<SysUser> queryResult = USERS.stream() .filter(obj -> obj.getPhone().equals(phone)) .collect(Collectors.toList()); return CommonResult.success(queryResult); } } - 测试

 
统一异常处理
上面参数验证时,验证的错误信息是通过BindingResult result参数进行接收的,比较麻烦。甚至是直接将异常堆栈信息返回给前端,不太友好,有的时候需要主动抛出业务异常,比如用户不能直接删除已绑定用户的角色。
创建业务异常类
package com.whh.valid.exception;
// 业务异常
public class BusinessException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    protected final String message;
    public BusinessException(String message) {
        this.message = message;
    }
    public BusinessException(String message,Throwable e) {
        super(message,e);
        this.message = message;
    }
    @Override
    public String getMessage() {
        return message;
    }
}
创建全局异常处理器
package com.whh.valid.exception;
import com.whh.valid.util.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Set;
/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 参数绑定异常类,用于表单验证时抛出异常处理
     */
    @ExceptionHandler(BindException.class)
    public CommonResult validatedBindException(BindException e) {
        log.error(e.getMessage(),e);
        BindingResult bindingResult = e.getBindingResult();
        FieldError fieldError = e.getFieldError();
        String message = "[" + e.getAllErrors().get(0).getDefaultMessage()+"]";
        return CommonResult.error(message);
    }
    /**
     * 用于方法形参中参数校验时抛出的异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public CommonResult handle(ValidationException e) {
        log.error(e.getMessage(),e);
        String errorInfo = "";
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations){
                errorInfo = errorInfo + "[" + item.getMessage() + "]";
            }
        }
        return CommonResult.error(errorInfo);
    }
    /**
     * 请求方式不支持
     * @param e
     * @return
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public CommonResult handleException(HttpRequestMethodNotSupportedException e){
        log.error(e.getMessage(),e);
        return CommonResult.error("不支持" + e.getMethod()+"请求");
    }
    /**
     * 拦截未知的运行时异常
     * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public CommonResult notFount(RuntimeException e){
        log.error("运行时异常",e);
        return CommonResult.error("运行时异常",e.getMessage());
    }
    /**
     * 系统异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public CommonResult handleException(Exception e){
        log.error(e.getMessage(),e);
        return CommonResult.error("服务器错误,请联系管理员");
    }
    /**
     * 业务异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(BusinessException.class)
    public CommonResult bussinessException(HttpServletRequest request,BusinessException e){
        log.error(e.getMessage());
        return CommonResult.error(e.getMessage());
    }
}
- @Slf4j注解:用作日志输出的,一般会在项目每个类的开头加入该注解,如果不写下面这段代码,并且想用log
 - @RestControllerAdvice:对Controller增强,捕获全局Spring MVC抛出的异常。
 - @ExceptionHandler(BindException.class):用来捕获指定的异常
 
修改控制器
删除方法中的BindingResult result参数,将错误直接抛给统一异常处理类去解决即可
测试

自定义验证信息源
修改配置文件(ValidatorConfig)
/**
     * 实体类字段校验国际化引入
     * */
    @Bean
    public Validator validator() {
//        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
//                .configure()
//                .addProperty("hibernate.validator.fail_fast","true")
//                .buildValidatorFactory();
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        // 设置messages资源信息
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        // 多个用逗号分割
        messageSource.setBasenames("classpath:/messages/validation/messages");
        // 设置字符集编码
        messageSource.setDefaultEncoding("UTF-8");
        validator.setValidationMessageSource(messageSource);
        // 设置验证相关参数
        Properties properties = new Properties();
        // 快速失败,有错即返回
        properties.setProperty("hibernate.validator.fail_fast", "true");
        validator.setValidationProperties(properties);
//        return validatorFactory.getValidator();
        return validator;
    }
添加信息源文件
├───resources
    └── messages
        └── validation
            └── messages.properties
# messages.properties
name.not.empty=用户名不能为空
email.not.valid=${validatedValue}是邮箱地址?
email.not.empty=邮箱不能为空
phone.not.valid=${validatedValue}是手机号?
phone.not.empty=手机号不能为空
password.size.valid=密码长度必须在{min}-{max}之间
id.not.empty=主键不能为空
修改实体类
message = "{name.not.empty}"
message = "{password.size.valid}"
message = "{email.not.valid}"
message = "{phone.not.valid}"
注解
| 注解 | 说明 | 
|---|---|
| @Null | 限制只能为null | 
| @NotNull | 限制必须不为null | 
| @AssertFalse | 限制必须为false | 
| @AssertTrue | 限制必须为true | 
| @DecimalMax(value) | 限制必须为一个不大于指定值的数字 | 
| @DecimalMin(value) | 限制必须为一个不小于指定值的数字 | 
| @Digits(integer,fraction) | 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction | 
| @Future | 限制必须是一个将来的日期 | 
| @Max(value) | 限制必须为一个不大于指定值的数字 | 
| @Min(value) | 限制必须为一个不小于指定值的数字 | 
| @Past | 限制必须是一个过去的日期 | 
| @Pattern(value) | 限制必须符合指定的正则表达式 | 
| @Size(max,min) | 限制字符长度必须在min到max之间 | 
| @Past | 验证注解的元素值(日期类型)比当前时间早 | 
| @NotEmpty | 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) | 
| @NotBlank | 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank | 
| 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 | 
参考
开撸!SpringBoot-表单验证-统一异常处理-自定义验证信息源
Spring方法级别数据校验
@Data注解 与 lombok
SpringBoot - Lombok使用详解3(@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor)
@Constraint注解配合自定义验证类型注解的开发
Spring Boot @RestControllerAdvice 统一异常处理
- 本文链接:https://wentianhao.github.io/2021/08/20/validation/
 - 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。
 
若没有本文 Issue,您可以使用 Comment 模版新建。