# validation
**Repository Path**: fashionbrot/validation
## Basic Information
- **Project Name**: validation
- **Description**: 参数验证框架,支持纯java、 spring、springboot、springcloud、dubbo 简单快捷的参数验证
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: https://my.oschina.net/u/3301366/blog/3100594
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2023-07-02
- **Last Updated**: 2025-03-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: valid, spring-boot-starter-validation, validation-spring
## README
# 1、项目介绍
### 简单好用的 java、spring、springmvc、springboot、springcloud 参数校验框架
#### validation 基于纯java 开发
#### validation-spring 基于spring框架封装的validation
#### spring-boot-starter-validation 基于springboot封装的validation-spring
##### github:https://github.com/fashionbrot/validation.git
##### gitee :https://gitee.com/fashionbrot/validation.git
# 2、使用环境介绍
#### 使用环境介绍
##### jdk8 => validation
##### spring4.0 >= validation-spring
##### springboot2.0 >= spring-boot-starter-validation
# 3、springmvc 引入
### 3.1 引入maven 配置 和 gradle配置
```xml
com.github.fashionbrot
validation-spring
4.0.2
```
```gradle
implementation 'com.github.fashionbrot:validation-spring:4.0.2'
```
### 3.2 springmvc 配置方式
```java
@Component
@Configuration
//localeParamName="lang" 开启国际化
//springProfilesActive="prod" springboot启动的环境
//@EnableValidatedConfig 开启validation 功能
@EnableValidatedConfig(localeParamName="lang",springProfilesActive="prod")
public class ValidConfig {
}
```
### 3.3 配置全局异常拦截
```java
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 violations = e.getViolations();
return violations.stream().map(m -> m.getMessage()).collect(Collectors.joining(","));// 慢速失败抛出异常信息
}
}
```
### 3.4 使用
```java
@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'",message = "验证码不能为空") String smsCode,
@NotEmpty(expression = "type!=null and type==2 and springProfilesActive=='default'",message = "密码不能为空") 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'" ,message = "验证码不能为空")
private String smsCode;
//如果expression 条件=true,则进行@NotEmpty的验证
@NotEmpty(expression = "expressionEntity.type!=null and expressionEntity.type==2 and springProfilesActive=='default'",message = "密码不能为空")
private String password;
}
}
```
# 4、springboot 接入
### 4.1 Maven引入,gradle引入
```xml
com.github.fashionbrot
spring-boot-starter-validation
4.0.2
```
```bash
#springboot 依赖
implementation 'com.github.fashionbrot:spring-boot-starter-validation:4.0.2'
```
### 4.2 配置方式
##### application.properties 中配置国际化默认中文
```properties
# 开启国际化 优先header读取lang,其次读取参数lang
validated.locale-param-name=lang
```
### 4.3配置全局异常拦截
```java
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 violations = e.getViolations();
return violations.stream().map(m -> m.getMessage()).collect(Collectors.joining(","));
}
}
```
### 4.4 在接口中使用
```java
/**
* @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();
}
}
```
# 4、注解介绍
#### @Validated 添加到方法上开启
|方法| 默认值 | 说明 |
|------|----------------------|--------------------------|
|Class>[] groups() default { }| {} | 校验组 |
|boolean failFast() default true| true | true 快速失败 |
|boolean validReturnValue() default false| false | 验证返回值 默认false |
#### @Valid 注解支持功能说明,作用于 参数、属性上使用
#### 用于参数如: `List` 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(message = "不能为空", groups = {InsertGroup.class})` | 用于分组校验,指定注解适用的校验组,例如 `InsertGroup.class`,以便在特定场景下执行相应的校验逻辑 |
| `String message() default "${validated.Length.message}";` | `@NotNull(message = "不能为空")` | 指定在验证失败时显示的错误消息内容 |
| `String expression() default ""` | `@NotEmpty(expression = "type!=null and type==1 and springProfilesActive=='prod'", message = "验证码不能为空") String smsCode` | 当 `expression` 条件为 `true` 时,执行 `@NotEmpty` 验证,适用于基于表达式的条件校验;表达式语法和mybatis xml if 中表达式语法一样 |
# 6、自定义注解介绍
#### (1)实现自定义注解的"注解",需要在自定义注解上添加该注解
```java
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 {};
}
```
#### (2)自定义注解必须实现该类
```java
package com.github.fashionbrot.constraint;
import java.lang.annotation.Annotation;
/**
* 自定义注解实现接口,调用顺序 isValid,modify
* @param Annotation
* @param T
*/
public interface ConstraintValidator {
/**
* 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;
}
}
```
#### (1)创建注解
```java
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 message() default "validated.AssertTrue.message";
/**
* 固定方法 验证组
* default @see com.github.fashionbrot.groups.DefaultGroup
* @return groups
*/
Class>[] groups() default {};
}
```
#### 创建注解实现类
```java
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 {
//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;
}
}
```
#### (3) 在接口上使用
```java
@Controller
public class Controller1{
@Validated(failFast = false)//TODO 添加该注解开启参数验证
public void test(@CustomAnnotation(defaultValue = "{\"id\":1,\"name\":\"张三\"}",modify = true) TestEntity test){
}
}
```
# 7使用国际化 【默认支持中文、英文,其他语言自己可添加】
```properties
# 开启国际化 优先header读取lang,其次读取参数lang
validated.locale-param-name=lang
```
##### 如果需要添加新语言,可以在 resources 目录下增加对应的属性文件。例如,添加俄语支持:
##### valid_ru_RU.properties
```properties
#valid_ru_RU.properties
validated.NotEmpty.message= `не должно быть пустым
```
#####在我们header 中可以配置参数 lang=ru_RU 并且message等于默认的${validated.NotEmpty.message}
```shell
lang=ru_RU message=${validated.NotEmpty.message} 则会提示:`не должно быть пустым`
lang=zh_CN message=${validated.NotEmpty.message} 则会提示:`不能为空`
lang=en_US message=${validated.NotEmpty.message} 则会提示:`must not be empty`
```
# 版权 | License
[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0)
# 捐赠 | Donate
> [捐赠记录,感谢你们的支持!](https://gitee.com/fashionbrot/validation/wikis/%E6%8D%90%E8%B5%A0%E8%AE%B0%E5%BD%95)