简单好用的 java、spring、springmvc、springboot、springcloud 参数校验框架
validation-spring 基于spring框架封装的validation
spring-boot-starter-validation 基于springboot封装的validation-spring
spring4.0 >= validation-spring
springboot2.0 >= spring-boot-starter-validation
3.1 引入maven 配置 和 gradle配置
<!-- springmvc 依赖-->
<dependency >
<groupId >com.github.fashionbrot</groupId >
<artifactId >validation-spring</artifactId >
<version >3.0.1</version >
</dependency >
implementation ' com.github.fashionbrot:validation-spring:3.0.1'
@ Component
@ Configuration
//localeParamName="lang" 开启国际化
//springProfilesActive="prod" springboot启动的环境
//@EnableValidatedConfig 开启validation 功能
@ EnableValidatedConfig (localeParamName ="lang" ,springProfilesActive ="prod" )
public class ValidConfig {
}
package com .github .fashionbrot .exception ;
import com .github .fashionbrot .constraint .Violation ;
import com .github .fashionbrot .util .ObjectUtil ;
import lombok .extern .slf4j .Slf4j ;
import org .springframework .http .HttpStatus ;
import org .springframework .validation .BindException ;
import org .springframework .web .bind .annotation .ExceptionHandler ;
import org .springframework .web .bind .annotation .ResponseStatus ;
import org .springframework .web .bind .annotation .RestControllerAdvice ;
import javax .validation .ConstraintViolation ;
import javax .validation .ConstraintViolationException ;
import java .util .List ;
import java .util .Set ;
import java .util .stream .Collectors ;
@ RestControllerAdvice
@ Slf4j
public class GlobalExceptionHandler {
@ ExceptionHandler (ValidatedException .class )
@ ResponseStatus (HttpStatus .OK )
public Object ValidatedException (ValidatedException e ) {
List <Violation > violations = e .getViolations ();
if (ObjectUtil .isEmpty (violations )){// 快速失败抛出异常信息
return e .getMsg ();
}else {
return violations .stream ().map (m -> m .getMsg ()).collect (Collectors .joining ("," ));// 慢速失败抛出异常信息
}
}
}
@ RequestMapping ("/expression" )
@ RestController
public class ExpressionController {
@ GetMapping ("/test1" )
@ ResponseBody
@ Validated (failFast = false ) //开启参数验证
public String test1 (Integer type ,
@ NotEmpty (expression = "type!=null and type==1 and springProfilesActive=='prod'" ,msg = "验证码不能为空" ) String smsCode ,
@ NotEmpty (expression = "type!=null and type==2 and springProfilesActive=='default'" ,msg = "密码不能为空" ) String password ){
return "ok" ;
}
@ GetMapping ("/test2" )
@ ResponseBody
@ Validated (failFast = false )//开启参数验证
public String test2 ( ExpressionEntity expression ){
return expression .toString ();
}
@ GetMapping ("/test3" )
@ ResponseBody
@ Validated (failFast = false )//开启参数验证
public String test3 ( Default1Entity entity ){
return entity .toString ();
}
@ Data
//@ValidatedParam("expression")//没有注解默认读取类名首字母小写,例如expressionEntity.type ; 有改注解则表达式中使用例如: expression.type
public class ExpressionEntity {
private Integer type ;
//如果expression 条件=true,则进行@NotEmpty的验证
@ NotEmpty (expression = "expressionEntity.type!=null and expressionEntity.type==1 and springProfilesActive=='prod'" ,msg = "验证码不能为空" )
private String smsCode ;
//如果expression 条件=true,则进行@NotEmpty的验证
@ NotEmpty (expression = "expressionEntity.type!=null and expressionEntity.type==2 and springProfilesActive=='default'" ,msg = "密码不能为空" )
private String password ;
}
}
<!-- springboot 依赖-->
<dependency >
<groupId >com.github.fashionbrot</groupId >
<artifactId >spring-boot-starter-validation</artifactId >
<version >3.0.1</version >
</dependency >
# springboot 依赖
implementation ' com.github.fashionbrot:spring-boot-starter-validation:3.0.1'
application.properties 中配置国际化默认中文
# 开启国际化 优先header读取lang,其次读取参数lang
validated.locale-param-name =lang
package com .github .fashionbrot .exception ;
import com .github .fashionbrot .constraint .Violation ;
import com .github .fashionbrot .util .ObjectUtil ;
import lombok .extern .slf4j .Slf4j ;
import org .springframework .http .HttpStatus ;
import org .springframework .validation .BindException ;
import org .springframework .web .bind .annotation .ExceptionHandler ;
import org .springframework .web .bind .annotation .ResponseStatus ;
import org .springframework .web .bind .annotation .RestControllerAdvice ;
import javax .validation .ConstraintViolation ;
import javax .validation .ConstraintViolationException ;
import java .util .List ;
import java .util .Set ;
import java .util .stream .Collectors ;
@ RestControllerAdvice
@ Slf4j
public class GlobalExceptionHandler {
@ ExceptionHandler (ValidatedException .class )
@ ResponseStatus (HttpStatus .OK )
public Object ValidatedException (ValidatedException e ) {
List <Violation > violations = e .getViolations ();
if (ObjectUtil .isEmpty (violations )){// 快速失败抛出异常信息
return e .getMsg ();
}else {
return violations .stream ().map (m -> m .getMsg ()).collect (Collectors .joining ("," ));// 慢速失败抛出异常信息
}
}
}
/**
* @author fashionbrot
*/
@ RestController
@ RequestMapping ("/vrv" )
public class ValidReturnValueController {
@ GetMapping ("test1" )
@ Validated (failFast = false ,validReturnValue = true )// 开启参数验证,failFast = false全部校验后抛出异常,validReturnValue = true 验证返回值
public ValidReturnValueEntity test1 (Integer type ){
return ValidReturnValueEntity .builder ().type (type ).build ();
}
}
方法
默认值
说明
Class<?>[] groups() default { }
{}
校验组
boolean failFast() default true
true
true 快速失败
boolean validReturnValue() default false
false
验证返回值 默认false
@Valid 注解支持功能说明,作用于 参数、属性上使用
用于参数如: List<UserReq>
userListReq 、UserReq[] userReqs 、List<基本类型> reqList、基本类型[] reqs
注解
作用类型
注解说明
AssertFalse
boolean、String
只能为false
AssertTrue
boolean String
只能为true
BankCard
String、CharSequence
验证银行卡
CreditCard
String、CharSequence
验证信用卡
IdCard
String、CharSequence
验证身份证
Email
String、CharSequence
验证邮箱格式
Digits
String、CharSequence
验证是否是数字
Default
BigDecimal、BigInteger、Short、Integer、Long、Float、Double、String、CharSequence
给属性设置默认值
Length
String、CharSequence
验证字符串长度
Max
Long、Integer、Short、Float、Double、BigDecimal、BigInteger
验证属性值不能大于设定值
Min
Long、Integer、Short、Float、Double、BigDecimal、BigInteger
验证属性值不能小于设定值
NotBlank
String、CharSequence
元素值不为空
NotEmpty
String、CharSequence、Collection、Map、Array
验证对象不为空
NotEqualLength
String、CharSequence、Collection、Map、Array
验证对象长度必须是设定值
NotNull
Object
验证对象不能为空
Pattern
String、CharSequence
验证正则表达式
Phone
String、CharSequence
验证手机号格式
Range
BigDecimal、BigInteger、Short、Integer、Long、Float、Double
验证属性值必须在 设定值之间
Contain
BigDecimal、BigInteger、Short、Integer、Long、Float、Double、String、CharSequence
验证属性值包含设定值
Size
Collection、Map、Array
验证集合、数组 size 在设定值值之间
方法名
示例
方法说明
Class<?>[] groups() default {}
@NotNull(msg = "不能为空", groups = {InsertGroup.class})
用于分组校验,指定注解适用的校验组,例如 InsertGroup.class
,以便在特定场景下执行相应的校验逻辑
String msg() default "${validated.Length.msg}";
@NotNull(msg = "不能为空")
指定在验证失败时显示的错误消息内容
String expression() default ""
@NotEmpty(expression = "type!=null and type==1 and springProfilesActive=='prod'", msg = "验证码不能为空") String smsCode
当 expression
条件为 true
时,执行 @NotEmpty
验证,适用于基于表达式的条件校验;表达式语法和mybatis xml if 中表达式语法一样
(1)实现自定义注解的"注解",需要在自定义注解上添加该注解
package com .github .fashionbrot .constraint ;
import java .lang .annotation .*;
@ Documented
@ Target ({ElementType .ANNOTATION_TYPE })
@ Retention (RetentionPolicy .RUNTIME )
public @interface Constraint {
/**
* 属性 参数 实现接口
* @return Class
*/
Class <? extends ConstraintValidator <? extends Annotation , ?>>[] validatedBy () default {};
}
package com .github .fashionbrot .constraint ;
import java .lang .annotation .Annotation ;
/**
* 自定义注解实现接口,调用顺序 isValid,modify
* @param <A> Annotation
* @param <T> T
*/
public interface ConstraintValidator <A extends Annotation , T > {
/**
* annotation all 返回false 抛出异常
* @param annotation annotation
* @param value value
* @param valueType valueType
* @return boolean
*/
boolean isValid (A annotation , T value ,Class <?> valueType );
/**
* 修改 value 值,常用于 加密解密字段、脱敏字段 、动态给定默认值、及各种自定义逻辑
* @param annotation annotation
* @param value value
* @param valueType valueType
* @return T
*/
default T modify (A annotation ,T value ,Class <?> valueType ){
return value ;
}
}
package com .github .fashionbrot .annotation ;
import com .github .fashionbrot .constraint .Constraint ;
import com .github .fashionbrot .constraint .CustomAnnotationConstraintValidator ;
import java .lang .annotation .*;
@ Documented
@ Target ({ElementType .FIELD , ElementType .PARAMETER })
@ Retention (RetentionPolicy .RUNTIME )
@ Constraint (validatedBy = {CustomAnnotationConstraintValidator .class }) //实现类
public @interface CustomAnnotation {
boolean modify () default true ;//自己定义
String defaultValue () default "" ;//自己定义
/**
* 固定方法 验证失败返回的错误信息
* @return
*/
String msg () default "validated.AssertTrue.msg" ;
/**
* 固定方法 验证组
* default @see com.github.fashionbrot.groups.DefaultGroup
* @return groups
*/
Class <?>[] groups () default {};
}
package com .github .fashionbrot .constraint ;
import com .alibaba .fastjson2 .JSON ;
import com .github .fashionbrot .TestEntity ;
import com .github .fashionbrot .annotation .CustomAnnotation ;
import com .github .fashionbrot .util .ObjectUtil ;
public class CustomAnnotationConstraintValidator implements ConstraintValidator <CustomAnnotation , Object > {
//TODO 自定义注解可以注入spring 容器 bean
@ Resource
private Environment environment ;
@ Override
public boolean isValid (CustomAnnotation annotation , Object value , Class <?> valueType ) {
//可根据自己逻辑进行拦截
return true ;
}
@ Override
public Object modify (CustomAnnotation annotation , Object value , Class <?> valueType ) {
if (annotation .modify () && value ==null ){
if (ObjectUtil .isNotEmpty (annotation .defaultValue ())){
TestEntity entity = JSON .parseObject (annotation .defaultValue (), TestEntity .class );
return entity ;
}else {
//可以根据需求动态修改
//TODO 比如加密解密、数据脱敏、增加默认值 等等
if (valueType == TestEntity .class ){
TestEntity entity = new TestEntity ();
entity .setId (2L );
entity .setName ("李四" );
return entity ;
}
}
}
return value ;
}
}
@ Controller
public class Controller1 {
@ Validated (failFast = false )//TODO 添加该注解开启参数验证
public void test (@ CustomAnnotation (defaultValue = "{\" id\" :1,\" name\" :\" 张三\" }" ,modify = true ) TestEntity test ){
}
}
7使用国际化 【默认支持中文、英文,其他语言自己可添加】
# 开启国际化 优先header读取lang,其次读取参数lang
validated.locale-param-name =lang
如果需要添加新语言,可以在 resources 目录下增加对应的属性文件。例如,添加俄语支持:
# valid_ru_RU.properties
validated.NotEmpty.msg = `не должно быть пустым
#####在我们header 中可以配置参数 lang=ru_RU 并且msg等于默认的${validated.NotEmpty.msg}
lang=ru_RU msg=${validated.NotEmpty.msg} 则会提示:` не должно быть пустым`
lang=zh_CN msg=${validated.NotEmpty.msg} 则会提示:` 不能为空`
lang=en_US msg=${validated.NotEmpty.msg} 则会提示:` must not be empty`
Apache License 2.0
捐赠记录,感谢你们的支持!