serv-参数校验
This commit is contained in:
@@ -0,0 +1,380 @@
|
|||||||
|
# 数据校验工具使用说明
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
这是一个灵活、可扩展的Java数据校验工具,支持对对象和Map进行多种类型的校验。
|
||||||
|
|
||||||
|
## 核心组件
|
||||||
|
|
||||||
|
### 1. ValidationParam - 校验参数对象
|
||||||
|
定义字段的校验规则,支持:
|
||||||
|
- 字段名称和中文标签
|
||||||
|
- 是否必传
|
||||||
|
- 字段类型校验
|
||||||
|
- 字符串长度限制
|
||||||
|
- 数字范围限制
|
||||||
|
- 正则表达式校验
|
||||||
|
- 自定义校验函数
|
||||||
|
- 预定义的校验方法(ValidateMethod)
|
||||||
|
|
||||||
|
### 2. ValidationResult - 校验结果对象
|
||||||
|
保存校验结果,包含:
|
||||||
|
- 是否校验通过
|
||||||
|
- 错误信息列表
|
||||||
|
- 第一个错误信息
|
||||||
|
- 错误数量统计
|
||||||
|
|
||||||
|
### 3. ValidationUtils - 校验工具类
|
||||||
|
执行校验逻辑,提供:
|
||||||
|
- 校验Java对象
|
||||||
|
- 校验Map对象
|
||||||
|
- 快捷方法:`requiredString()`, `requiredNumber()`, `email()`, `phone()`
|
||||||
|
|
||||||
|
### 4. ValidateMethod - 校验方法接口
|
||||||
|
预定义的专业校验方法,已实现:
|
||||||
|
- **PasswordValidateMethod** - 密码校验
|
||||||
|
- **IdCardValidateMethod** - 身份证号校验
|
||||||
|
- **PhoneValidateMethod** - 手机号码校验
|
||||||
|
- **EmailValidateMethod** - 邮箱地址校验
|
||||||
|
- **UrlValidateMethod** - URL链接校验
|
||||||
|
- **BankCardValidateMethod** - 银行卡号校验
|
||||||
|
- **ChineseValidateMethod** - 中文字符校验
|
||||||
|
|
||||||
|
### 5. ValidateMethodType - 校验方法类型枚举 ⭐推荐使用
|
||||||
|
枚举类型指向预定义的校验方法,使用更简洁:
|
||||||
|
- **PASSWORD** - 密码校验(6-20位,字母+数字)
|
||||||
|
- **STRONG_PASSWORD** - 强密码校验(8-20位,大小写+数字+特殊字符)
|
||||||
|
- **ID_CARD** - 身份证号校验
|
||||||
|
- **PHONE** - 手机号码校验(中国大陆)
|
||||||
|
- **PHONE_LOOSE** - 手机号码校验(支持大陆/香港/台湾)
|
||||||
|
- **EMAIL** - 邮箱地址校验
|
||||||
|
- **URL** - URL链接校验
|
||||||
|
- **HTTPS_URL** - HTTPS链接校验
|
||||||
|
- **BANK_CARD** - 银行卡号校验
|
||||||
|
- **CHINESE** - 中文字符校验(纯中文)
|
||||||
|
- **CHINESE_WITH_PUNCTUATION** - 中文字符校验(允许标点)
|
||||||
|
|
||||||
|
## 基本使用示例
|
||||||
|
|
||||||
|
### 1. 使用枚举类型校验(⭐推荐)
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<ValidationParam> params = Arrays.asList(
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("password")
|
||||||
|
.fieldLabel("密码")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.PASSWORD) // 使用枚举
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("email")
|
||||||
|
.fieldLabel("邮箱")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.EMAIL) // 使用枚举
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("phone")
|
||||||
|
.fieldLabel("手机号")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.PHONE) // 使用枚举
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("idCard")
|
||||||
|
.fieldLabel("身份证号")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.ID_CARD) // 使用枚举
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
ValidationResult result = ValidationUtils.validateMap(data, params);
|
||||||
|
if (!result.isValid()) {
|
||||||
|
System.out.println(result.getFirstError());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 简单字段校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<ValidationParam> params = Arrays.asList(
|
||||||
|
ValidationUtils.requiredString("username", "用户名", 3, 20),
|
||||||
|
ValidationUtils.email("email", "邮箱", true),
|
||||||
|
ValidationUtils.phone("phone", "手机号", false)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 校验对象
|
||||||
|
ValidationResult result = ValidationUtils.validate(userObject, params);
|
||||||
|
|
||||||
|
// 校验Map
|
||||||
|
ValidationResult result = ValidationUtils.validateMap(userMap, params);
|
||||||
|
|
||||||
|
// 检查结果
|
||||||
|
if (result.isValid()) {
|
||||||
|
// 校验通过
|
||||||
|
} else {
|
||||||
|
// 获取错误信息
|
||||||
|
String firstError = result.getFirstError();
|
||||||
|
String allErrors = result.getAllErrors();
|
||||||
|
List<String> errors = result.getErrors();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 使用ValidateMethod进行专业校验(兼容旧方式)
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<ValidationParam> params = Arrays.asList(
|
||||||
|
// 方式1:使用枚举(推荐)
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("password")
|
||||||
|
.fieldLabel("密码")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.STRONG_PASSWORD) // 使用预定义的强密码
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
// 方式2:直接实例化(如需自定义参数)
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("password2")
|
||||||
|
.fieldLabel("自定义密码")
|
||||||
|
.required()
|
||||||
|
.validateMethod(new PasswordValidateMethod(8, 20, true, true, true, true))
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
// 身份证号校验
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("idCard")
|
||||||
|
.fieldLabel("身份证号")
|
||||||
|
.required()
|
||||||
|
.validateMethod(new IdCardValidateMethod())
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
// 手机号校验
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("phone")
|
||||||
|
.fieldLabel("手机号")
|
||||||
|
.required()
|
||||||
|
.validateMethod(new PhoneValidateMethod())
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
// 限制域名的邮箱校验
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("email")
|
||||||
|
.fieldLabel("邮箱")
|
||||||
|
.required()
|
||||||
|
.validateMethod(new EmailValidateMethod(new String[]{"company.com"}))
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
ValidationResult result = ValidationUtils.validateMap(data, params);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 自定义校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
ValidationParam param = ValidationParam.builder()
|
||||||
|
.fieldName("age")
|
||||||
|
.fieldLabel("年龄")
|
||||||
|
.required()
|
||||||
|
.customValidator(value -> {
|
||||||
|
Integer age = (Integer) value;
|
||||||
|
return age >= 18 && age <= 60;
|
||||||
|
})
|
||||||
|
.customErrorMessage("年龄必须在18-60岁之间")
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 复合校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
List<ValidationParam> params = Arrays.asList(
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("username")
|
||||||
|
.fieldLabel("用户名")
|
||||||
|
.required()
|
||||||
|
.fieldType(String.class)
|
||||||
|
.minLength(3)
|
||||||
|
.maxLength(20)
|
||||||
|
.pattern("^[a-zA-Z0-9_]+$")
|
||||||
|
.patternDesc("只能包含字母、数字和下划线")
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("password")
|
||||||
|
.fieldLabel("密码")
|
||||||
|
.required()
|
||||||
|
.minLength(6)
|
||||||
|
.validateMethod(new PasswordValidateMethod())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 预定义校验方法详解
|
||||||
|
|
||||||
|
### PasswordValidateMethod - 密码校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 默认规则:6-20位,必须包含字母和数字
|
||||||
|
new PasswordValidateMethod()
|
||||||
|
|
||||||
|
// 自定义规则
|
||||||
|
new PasswordValidateMethod(
|
||||||
|
8, // 最小长度
|
||||||
|
20, // 最大长度
|
||||||
|
true, // 需要大写字母
|
||||||
|
true, // 需要小写字母
|
||||||
|
true, // 需要数字
|
||||||
|
true // 需要特殊字符
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### IdCardValidateMethod - 身份证号校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 支持15位和18位身份证号
|
||||||
|
// 自动校验:格式、省份代码、出生日期、校验码
|
||||||
|
new IdCardValidateMethod()
|
||||||
|
```
|
||||||
|
|
||||||
|
### PhoneValidateMethod - 手机号码校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 严格模式:仅中国大陆手机号
|
||||||
|
new PhoneValidateMethod()
|
||||||
|
|
||||||
|
// 宽松模式:支持大陆、香港、台湾
|
||||||
|
new PhoneValidateMethod(false)
|
||||||
|
```
|
||||||
|
|
||||||
|
### EmailValidateMethod - 邮箱地址校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 允许所有域名
|
||||||
|
new EmailValidateMethod()
|
||||||
|
|
||||||
|
// 限制特定域名
|
||||||
|
new EmailValidateMethod(new String[]{"company.com", "example.com"})
|
||||||
|
```
|
||||||
|
|
||||||
|
### UrlValidateMethod - URL链接校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 允许HTTP和HTTPS
|
||||||
|
new UrlValidateMethod()
|
||||||
|
|
||||||
|
// 仅允许HTTPS
|
||||||
|
new UrlValidateMethod(true)
|
||||||
|
```
|
||||||
|
|
||||||
|
### BankCardValidateMethod - 银行卡号校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 使用Luhn算法校验银行卡号
|
||||||
|
new BankCardValidateMethod()
|
||||||
|
```
|
||||||
|
|
||||||
|
### ChineseValidateMethod - 中文字符校验
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 仅纯中文字符
|
||||||
|
new ChineseValidateMethod()
|
||||||
|
|
||||||
|
// 允许中文标点符号
|
||||||
|
new ChineseValidateMethod(true)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 在Controller中使用
|
||||||
|
|
||||||
|
```java
|
||||||
|
@PostMapping("/register")
|
||||||
|
public ResultDomain<User> register(@RequestBody Map<String, Object> params) {
|
||||||
|
// 定义校验规则(使用枚举,更简洁)
|
||||||
|
List<ValidationParam> validationParams = Arrays.asList(
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("username")
|
||||||
|
.fieldLabel("用户名")
|
||||||
|
.required()
|
||||||
|
.minLength(3)
|
||||||
|
.maxLength(20)
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("password")
|
||||||
|
.fieldLabel("密码")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.PASSWORD) // 使用枚举!
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("email")
|
||||||
|
.fieldLabel("邮箱")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.EMAIL) // 使用枚举!
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ValidationParam.builder()
|
||||||
|
.fieldName("phone")
|
||||||
|
.fieldLabel("手机号")
|
||||||
|
.required()
|
||||||
|
.validateMethod(ValidateMethodType.PHONE) // 使用枚举!
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 执行校验
|
||||||
|
ValidationResult validationResult = ValidationUtils.validateMap(params, validationParams);
|
||||||
|
|
||||||
|
if (!validationResult.isValid()) {
|
||||||
|
ResultDomain<User> result = new ResultDomain<>();
|
||||||
|
result.fail(validationResult.getFirstError());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验通过,继续业务逻辑
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 自定义ValidateMethod
|
||||||
|
|
||||||
|
如需添加新的校验方法,只需实现`ValidateMethod`接口:
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class CustomValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
// 实现校验逻辑
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return "自定义错误信息";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "自定义校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 优势
|
||||||
|
|
||||||
|
1. **简洁性**:使用枚举类型,无需每次new对象 ⭐
|
||||||
|
2. **灵活性**:支持多种校验方式组合使用
|
||||||
|
3. **可扩展性**:易于添加新的校验方法
|
||||||
|
4. **可读性**:Builder模式让代码清晰易懂
|
||||||
|
5. **可复用性**:预定义的校验方法可在项目中重复使用
|
||||||
|
6. **专业性**:内置多种常用的专业校验算法(身份证、银行卡等)
|
||||||
|
7. **类型安全**:枚举类型提供编译时类型检查
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **推荐使用枚举类型**:`ValidateMethodType` 比直接 `new` 对象更简洁
|
||||||
|
2. 校验顺序:必填 -> 类型 -> 长度/范围 -> 正则 -> 自定义 -> ValidateMethodType -> ValidateMethod
|
||||||
|
3. ValidateMethod和customValidator可以同时使用,都会执行
|
||||||
|
4. 当值为null且非必填时,会跳过后续所有校验
|
||||||
|
5. 错误信息会累积,可以获取所有错误或只获取第一个错误
|
||||||
|
6. 枚举方式和实例方式可以并存,但推荐统一使用枚举方式
|
||||||
|
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
package org.xyzh.common.utils.validation;
|
||||||
|
|
||||||
|
import org.xyzh.common.utils.validation.method.ValidateMethod;
|
||||||
|
import org.xyzh.common.utils.validation.method.ValidateMethodType;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验参数对象,定义字段的校验规则
|
||||||
|
* @filename ValidationParam.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class ValidationParam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 字段名称
|
||||||
|
*/
|
||||||
|
private String fieldName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 字段中文名称(用于错误提示)
|
||||||
|
*/
|
||||||
|
private String fieldLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否必传
|
||||||
|
*/
|
||||||
|
private boolean required;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 字段类型
|
||||||
|
*/
|
||||||
|
private Class<?> fieldType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 最小长度(字符串)
|
||||||
|
*/
|
||||||
|
private Integer minLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 最大长度(字符串)
|
||||||
|
*/
|
||||||
|
private Integer maxLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 最小值(数字)
|
||||||
|
*/
|
||||||
|
private Number minValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 最大值(数字)
|
||||||
|
*/
|
||||||
|
private Number maxValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 正则表达式
|
||||||
|
*/
|
||||||
|
private String pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 正则表达式描述(用于错误提示)
|
||||||
|
*/
|
||||||
|
private String patternDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 自定义校验函数
|
||||||
|
*/
|
||||||
|
private Predicate<Object> customValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 自定义校验失败消息
|
||||||
|
*/
|
||||||
|
private String customErrorMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否允许为空字符串(默认不允许)
|
||||||
|
*/
|
||||||
|
private boolean allowEmpty = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法(使用预定义的校验方法)
|
||||||
|
*/
|
||||||
|
private ValidateMethod validateMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法类型枚举
|
||||||
|
*/
|
||||||
|
private ValidateMethodType validateMethodType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法配置参数(用于需要自定义参数的校验方法)
|
||||||
|
*/
|
||||||
|
private Object[] methodParams;
|
||||||
|
|
||||||
|
// 私有构造函数,使用Builder模式
|
||||||
|
private ValidationParam() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldName() {
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldLabel() {
|
||||||
|
return fieldLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequired() {
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getFieldType() {
|
||||||
|
return fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMinLength() {
|
||||||
|
return minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxLength() {
|
||||||
|
return maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number getMinValue() {
|
||||||
|
return minValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Number getMaxValue() {
|
||||||
|
return maxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPatternDesc() {
|
||||||
|
return patternDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Predicate<Object> getCustomValidator() {
|
||||||
|
return customValidator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCustomErrorMessage() {
|
||||||
|
return customErrorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowEmpty() {
|
||||||
|
return allowEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidateMethod getValidateMethod() {
|
||||||
|
return validateMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidateMethodType getValidateMethodType() {
|
||||||
|
return validateMethodType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getMethodParams() {
|
||||||
|
return methodParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Builder类用于构建ValidationParam对象
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
private ValidationParam param = new ValidationParam();
|
||||||
|
|
||||||
|
public Builder fieldName(String fieldName) {
|
||||||
|
param.fieldName = fieldName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fieldLabel(String fieldLabel) {
|
||||||
|
param.fieldLabel = fieldLabel;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder required(boolean required) {
|
||||||
|
param.required = required;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder required() {
|
||||||
|
param.required = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder fieldType(Class<?> fieldType) {
|
||||||
|
param.fieldType = fieldType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder minLength(Integer minLength) {
|
||||||
|
param.minLength = minLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder maxLength(Integer maxLength) {
|
||||||
|
param.maxLength = maxLength;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder minValue(Number minValue) {
|
||||||
|
param.minValue = minValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder maxValue(Number maxValue) {
|
||||||
|
param.maxValue = maxValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder pattern(String pattern) {
|
||||||
|
param.pattern = pattern;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder patternDesc(String patternDesc) {
|
||||||
|
param.patternDesc = patternDesc;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder customValidator(Predicate<Object> customValidator) {
|
||||||
|
param.customValidator = customValidator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder customErrorMessage(String customErrorMessage) {
|
||||||
|
param.customErrorMessage = customErrorMessage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder allowEmpty(boolean allowEmpty) {
|
||||||
|
param.allowEmpty = allowEmpty;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder validateMethod(ValidateMethod validateMethod) {
|
||||||
|
param.validateMethod = validateMethod;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder validateMethod(ValidateMethodType methodType) {
|
||||||
|
param.validateMethodType = methodType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder validateMethod(ValidateMethodType methodType, Object... params) {
|
||||||
|
param.validateMethodType = methodType;
|
||||||
|
param.methodParams = params;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationParam build() {
|
||||||
|
if (param.fieldName == null || param.fieldName.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("fieldName不能为空");
|
||||||
|
}
|
||||||
|
if (param.fieldLabel == null || param.fieldLabel.isEmpty()) {
|
||||||
|
param.fieldLabel = param.fieldName;
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建Builder对象
|
||||||
|
* @return Builder
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package org.xyzh.common.utils.validation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验结果类
|
||||||
|
* @filename ValidationResult.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class ValidationResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否校验通过
|
||||||
|
*/
|
||||||
|
private boolean valid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 错误信息列表
|
||||||
|
*/
|
||||||
|
private List<String> errors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 第一个错误信息
|
||||||
|
*/
|
||||||
|
private String firstError;
|
||||||
|
|
||||||
|
public ValidationResult() {
|
||||||
|
this.valid = true;
|
||||||
|
this.errors = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValid(boolean valid) {
|
||||||
|
this.valid = valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getErrors() {
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstError() {
|
||||||
|
return firstError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 添加错误信息
|
||||||
|
* @param error 错误信息
|
||||||
|
*/
|
||||||
|
public void addError(String error) {
|
||||||
|
this.valid = false;
|
||||||
|
this.errors.add(error);
|
||||||
|
if (this.firstError == null) {
|
||||||
|
this.firstError = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取所有错误信息的字符串
|
||||||
|
* @return 错误信息字符串
|
||||||
|
*/
|
||||||
|
public String getAllErrors() {
|
||||||
|
return String.join("; ", errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 是否有错误
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean hasErrors() {
|
||||||
|
return !valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取错误数量
|
||||||
|
* @return 错误数量
|
||||||
|
*/
|
||||||
|
public int getErrorCount() {
|
||||||
|
return errors.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ValidationResult{" +
|
||||||
|
"valid=" + valid +
|
||||||
|
", errorCount=" + errors.size() +
|
||||||
|
", errors=" + errors +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,321 @@
|
|||||||
|
package org.xyzh.common.utils.validation;
|
||||||
|
|
||||||
|
import org.xyzh.common.utils.validation.method.ValidateMethod;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验工具类
|
||||||
|
* @filename ValidationUtils.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class ValidationUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验对象
|
||||||
|
* @param obj 待校验的对象
|
||||||
|
* @param validationParams 校验参数列表
|
||||||
|
* @return ValidationResult 校验结果
|
||||||
|
*/
|
||||||
|
public static ValidationResult validate(Object obj, List<ValidationParam> validationParams) {
|
||||||
|
ValidationResult result = new ValidationResult();
|
||||||
|
|
||||||
|
if (obj == null) {
|
||||||
|
result.addError("待校验对象不能为null");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validationParams == null || validationParams.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ValidationParam param : validationParams) {
|
||||||
|
try {
|
||||||
|
Object fieldValue = getFieldValue(obj, param.getFieldName());
|
||||||
|
validateField(param, fieldValue, result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError(param.getFieldLabel() + "字段获取失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验Map对象
|
||||||
|
* @param map 待校验的Map
|
||||||
|
* @param validationParams 校验参数列表
|
||||||
|
* @return ValidationResult 校验结果
|
||||||
|
*/
|
||||||
|
public static ValidationResult validateMap(Map<String, Object> map, List<ValidationParam> validationParams) {
|
||||||
|
ValidationResult result = new ValidationResult();
|
||||||
|
|
||||||
|
if (map == null) {
|
||||||
|
result.addError("待校验Map不能为null");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validationParams == null || validationParams.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ValidationParam param : validationParams) {
|
||||||
|
Object fieldValue = map.get(param.getFieldName());
|
||||||
|
validateField(param, fieldValue, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验单个字段
|
||||||
|
* @param param 校验参数
|
||||||
|
* @param fieldValue 字段值
|
||||||
|
* @param result 校验结果
|
||||||
|
*/
|
||||||
|
private static void validateField(ValidationParam param, Object fieldValue, ValidationResult result) {
|
||||||
|
String fieldLabel = param.getFieldLabel();
|
||||||
|
|
||||||
|
// 1. 必填校验
|
||||||
|
if (param.isRequired()) {
|
||||||
|
if (fieldValue == null) {
|
||||||
|
result.addError(fieldLabel + "不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fieldValue instanceof String) {
|
||||||
|
String strValue = (String) fieldValue;
|
||||||
|
if (!param.isAllowEmpty() && strValue.trim().isEmpty()) {
|
||||||
|
result.addError(fieldLabel + "不能为空字符串");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果值为null且非必填,跳过后续校验
|
||||||
|
if (fieldValue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 类型校验
|
||||||
|
if (param.getFieldType() != null) {
|
||||||
|
if (!param.getFieldType().isAssignableFrom(fieldValue.getClass())) {
|
||||||
|
result.addError(fieldLabel + "类型错误,期望类型: " + param.getFieldType().getSimpleName() +
|
||||||
|
", 实际类型: " + fieldValue.getClass().getSimpleName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 字符串长度校验
|
||||||
|
if (fieldValue instanceof String) {
|
||||||
|
String strValue = (String) fieldValue;
|
||||||
|
if (param.getMinLength() != null && strValue.length() < param.getMinLength()) {
|
||||||
|
result.addError(fieldLabel + "长度不能少于" + param.getMinLength() + "个字符");
|
||||||
|
}
|
||||||
|
if (param.getMaxLength() != null && strValue.length() > param.getMaxLength()) {
|
||||||
|
result.addError(fieldLabel + "长度不能超过" + param.getMaxLength() + "个字符");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 数字范围校验
|
||||||
|
if (fieldValue instanceof Number) {
|
||||||
|
double numValue = ((Number) fieldValue).doubleValue();
|
||||||
|
if (param.getMinValue() != null && numValue < param.getMinValue().doubleValue()) {
|
||||||
|
result.addError(fieldLabel + "不能小于" + param.getMinValue());
|
||||||
|
}
|
||||||
|
if (param.getMaxValue() != null && numValue > param.getMaxValue().doubleValue()) {
|
||||||
|
result.addError(fieldLabel + "不能大于" + param.getMaxValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 正则表达式校验
|
||||||
|
if (param.getPattern() != null && fieldValue instanceof String) {
|
||||||
|
String strValue = (String) fieldValue;
|
||||||
|
if (!Pattern.matches(param.getPattern(), strValue)) {
|
||||||
|
String errorMsg = fieldLabel + "格式不正确";
|
||||||
|
if (param.getPatternDesc() != null) {
|
||||||
|
errorMsg += "," + param.getPatternDesc();
|
||||||
|
}
|
||||||
|
result.addError(errorMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 自定义校验
|
||||||
|
if (param.getCustomValidator() != null) {
|
||||||
|
try {
|
||||||
|
if (!param.getCustomValidator().test(fieldValue)) {
|
||||||
|
String errorMsg = param.getCustomErrorMessage();
|
||||||
|
if (errorMsg == null || errorMsg.isEmpty()) {
|
||||||
|
errorMsg = fieldLabel + "校验失败";
|
||||||
|
}
|
||||||
|
result.addError(errorMsg);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError(fieldLabel + "自定义校验异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. 使用ValidateMethod校验(枚举类型)
|
||||||
|
if (param.getValidateMethodType() != null) {
|
||||||
|
try {
|
||||||
|
ValidateMethod method = param.getValidateMethodType().createInstance();
|
||||||
|
if (!method.validate(fieldValue)) {
|
||||||
|
String errorMsg = method.getErrorMessage();
|
||||||
|
if (errorMsg != null && !errorMsg.isEmpty()) {
|
||||||
|
result.addError(errorMsg);
|
||||||
|
} else {
|
||||||
|
result.addError(fieldLabel + "校验失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError(fieldLabel + "校验异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8. 使用ValidateMethod校验(直接传入实例,保留兼容性)
|
||||||
|
if (param.getValidateMethod() != null) {
|
||||||
|
try {
|
||||||
|
if (!param.getValidateMethod().validate(fieldValue)) {
|
||||||
|
String errorMsg = param.getValidateMethod().getErrorMessage();
|
||||||
|
if (errorMsg != null && !errorMsg.isEmpty()) {
|
||||||
|
result.addError(errorMsg);
|
||||||
|
} else {
|
||||||
|
result.addError(fieldLabel + "校验失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError(fieldLabel + "校验异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取对象字段值(支持getter方法和直接访问)
|
||||||
|
* @param obj 对象
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @return 字段值
|
||||||
|
* @throws Exception 异常
|
||||||
|
*/
|
||||||
|
private static Object getFieldValue(Object obj, String fieldName) throws Exception {
|
||||||
|
if (obj instanceof Map) {
|
||||||
|
return ((Map<?, ?>) obj).get(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?> clazz = obj.getClass();
|
||||||
|
|
||||||
|
// 首先尝试getter方法
|
||||||
|
try {
|
||||||
|
String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
|
||||||
|
return clazz.getMethod(getterName).invoke(obj);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
// getter方法不存在,尝试直接访问字段
|
||||||
|
try {
|
||||||
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field.get(obj);
|
||||||
|
} catch (NoSuchFieldException ex) {
|
||||||
|
// 尝试父类
|
||||||
|
Class<?> superClass = clazz.getSuperclass();
|
||||||
|
if (superClass != null) {
|
||||||
|
Field field = superClass.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field.get(obj);
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 快速创建必填字符串校验参数
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @param fieldLabel 字段标签
|
||||||
|
* @return ValidationParam
|
||||||
|
*/
|
||||||
|
public static ValidationParam requiredString(String fieldName, String fieldLabel) {
|
||||||
|
return ValidationParam.builder()
|
||||||
|
.fieldName(fieldName)
|
||||||
|
.fieldLabel(fieldLabel)
|
||||||
|
.required()
|
||||||
|
.fieldType(String.class)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 快速创建必填字符串校验参数(带长度限制)
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @param fieldLabel 字段标签
|
||||||
|
* @param minLength 最小长度
|
||||||
|
* @param maxLength 最大长度
|
||||||
|
* @return ValidationParam
|
||||||
|
*/
|
||||||
|
public static ValidationParam requiredString(String fieldName, String fieldLabel, int minLength, int maxLength) {
|
||||||
|
return ValidationParam.builder()
|
||||||
|
.fieldName(fieldName)
|
||||||
|
.fieldLabel(fieldLabel)
|
||||||
|
.required()
|
||||||
|
.fieldType(String.class)
|
||||||
|
.minLength(minLength)
|
||||||
|
.maxLength(maxLength)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 快速创建必填数字校验参数
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @param fieldLabel 字段标签
|
||||||
|
* @param minValue 最小值
|
||||||
|
* @param maxValue 最大值
|
||||||
|
* @return ValidationParam
|
||||||
|
*/
|
||||||
|
public static ValidationParam requiredNumber(String fieldName, String fieldLabel, Number minValue, Number maxValue) {
|
||||||
|
return ValidationParam.builder()
|
||||||
|
.fieldName(fieldName)
|
||||||
|
.fieldLabel(fieldLabel)
|
||||||
|
.required()
|
||||||
|
.minValue(minValue)
|
||||||
|
.maxValue(maxValue)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 快速创建邮箱校验参数
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @param fieldLabel 字段标签
|
||||||
|
* @param required 是否必填
|
||||||
|
* @return ValidationParam
|
||||||
|
*/
|
||||||
|
public static ValidationParam email(String fieldName, String fieldLabel, boolean required) {
|
||||||
|
return ValidationParam.builder()
|
||||||
|
.fieldName(fieldName)
|
||||||
|
.fieldLabel(fieldLabel)
|
||||||
|
.required(required)
|
||||||
|
.fieldType(String.class)
|
||||||
|
.pattern("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")
|
||||||
|
.patternDesc("请输入有效的邮箱地址")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 快速创建手机号校验参数
|
||||||
|
* @param fieldName 字段名
|
||||||
|
* @param fieldLabel 字段标签
|
||||||
|
* @param required 是否必填
|
||||||
|
* @return ValidationParam
|
||||||
|
*/
|
||||||
|
public static ValidationParam phone(String fieldName, String fieldLabel, boolean required) {
|
||||||
|
return ValidationParam.builder()
|
||||||
|
.fieldName(fieldName)
|
||||||
|
.fieldLabel(fieldLabel)
|
||||||
|
.required(required)
|
||||||
|
.fieldType(String.class)
|
||||||
|
.pattern("^1[3-9]\\d{9}$")
|
||||||
|
.patternDesc("请输入有效的手机号码")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 银行卡号校验方法(Luhn算法)
|
||||||
|
* @filename BankCardValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class BankCardValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String cardNumber = ((String) value).replaceAll("\\s", "");
|
||||||
|
|
||||||
|
// 长度校验(银行卡号通常为16-19位)
|
||||||
|
if (cardNumber.length() < 16 || cardNumber.length() > 19) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数字校验
|
||||||
|
if (!cardNumber.matches("^\\d+$")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Luhn算法校验
|
||||||
|
return luhnCheck(cardNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Luhn算法校验(银行卡校验算法)
|
||||||
|
* @param cardNumber 银行卡号
|
||||||
|
* @return boolean 是否通过校验
|
||||||
|
*/
|
||||||
|
private boolean luhnCheck(String cardNumber) {
|
||||||
|
int sum = 0;
|
||||||
|
boolean alternate = false;
|
||||||
|
|
||||||
|
// 从右向左遍历
|
||||||
|
for (int i = cardNumber.length() - 1; i >= 0; i--) {
|
||||||
|
int digit = Character.getNumericValue(cardNumber.charAt(i));
|
||||||
|
|
||||||
|
if (alternate) {
|
||||||
|
digit *= 2;
|
||||||
|
if (digit > 9) {
|
||||||
|
digit = digit - 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sum += digit;
|
||||||
|
alternate = !alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum % 10 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return "请输入有效的银行卡号";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "银行卡号校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 中文字符校验方法
|
||||||
|
* @filename ChineseValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class ChineseValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
// 中文字符正则(包括中文标点符号)
|
||||||
|
private static final Pattern CHINESE_PATTERN = Pattern.compile("^[\u4e00-\u9fa5]+$");
|
||||||
|
|
||||||
|
private final boolean allowPunctuation; // 是否允许中文标点符号
|
||||||
|
|
||||||
|
public ChineseValidateMethod() {
|
||||||
|
this.allowPunctuation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChineseValidateMethod(boolean allowPunctuation) {
|
||||||
|
this.allowPunctuation = allowPunctuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String str = (String) value;
|
||||||
|
|
||||||
|
if (allowPunctuation) {
|
||||||
|
// 允许中文字符和中文标点符号
|
||||||
|
return Pattern.matches("^[\u4e00-\u9fa5\\u3000-\\u303f]+$", str);
|
||||||
|
} else {
|
||||||
|
// 仅允许纯中文字符
|
||||||
|
return CHINESE_PATTERN.matcher(str).matches();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return allowPunctuation ? "请输入中文字符" : "请输入纯中文字符(不含标点符号)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "中文字符校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 邮箱校验方法
|
||||||
|
* @filename EmailValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class EmailValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
// 邮箱正则表达式
|
||||||
|
private static final Pattern EMAIL_PATTERN = Pattern.compile(
|
||||||
|
"^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"
|
||||||
|
);
|
||||||
|
|
||||||
|
private final String[] allowedDomains; // 允许的域名列表
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 默认构造函数,允许所有域名
|
||||||
|
*/
|
||||||
|
public EmailValidateMethod() {
|
||||||
|
this.allowedDomains = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 限制域名的构造函数
|
||||||
|
* @param allowedDomains 允许的域名列表,例如:["company.com", "example.com"]
|
||||||
|
*/
|
||||||
|
public EmailValidateMethod(String[] allowedDomains) {
|
||||||
|
this.allowedDomains = allowedDomains;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String email = ((String) value).trim().toLowerCase();
|
||||||
|
|
||||||
|
// 基本格式校验
|
||||||
|
if (!EMAIL_PATTERN.matcher(email).matches()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 域名限制校验
|
||||||
|
if (allowedDomains != null && allowedDomains.length > 0) {
|
||||||
|
boolean domainMatched = false;
|
||||||
|
for (String domain : allowedDomains) {
|
||||||
|
if (email.endsWith("@" + domain.toLowerCase())) {
|
||||||
|
domainMatched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domainMatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
if (allowedDomains != null && allowedDomains.length > 0) {
|
||||||
|
return "请输入有效的邮箱地址(仅支持: " + String.join(", ", allowedDomains) + ")";
|
||||||
|
}
|
||||||
|
return "请输入有效的邮箱地址";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "邮箱校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 身份证号码校验方法(支持15位和18位身份证)
|
||||||
|
* @filename IdCardValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class IdCardValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
// 加权因子
|
||||||
|
private static final int[] WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
|
||||||
|
|
||||||
|
// 校验码对应值
|
||||||
|
private static final char[] VALIDATE_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
|
||||||
|
|
||||||
|
// 省份代码
|
||||||
|
private static final Map<String, String> PROVINCE_CODES = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
PROVINCE_CODES.put("11", "北京");
|
||||||
|
PROVINCE_CODES.put("12", "天津");
|
||||||
|
PROVINCE_CODES.put("13", "河北");
|
||||||
|
PROVINCE_CODES.put("14", "山西");
|
||||||
|
PROVINCE_CODES.put("15", "内蒙古");
|
||||||
|
PROVINCE_CODES.put("21", "辽宁");
|
||||||
|
PROVINCE_CODES.put("22", "吉林");
|
||||||
|
PROVINCE_CODES.put("23", "黑龙江");
|
||||||
|
PROVINCE_CODES.put("31", "上海");
|
||||||
|
PROVINCE_CODES.put("32", "江苏");
|
||||||
|
PROVINCE_CODES.put("33", "浙江");
|
||||||
|
PROVINCE_CODES.put("34", "安徽");
|
||||||
|
PROVINCE_CODES.put("35", "福建");
|
||||||
|
PROVINCE_CODES.put("36", "江西");
|
||||||
|
PROVINCE_CODES.put("37", "山东");
|
||||||
|
PROVINCE_CODES.put("41", "河南");
|
||||||
|
PROVINCE_CODES.put("42", "湖北");
|
||||||
|
PROVINCE_CODES.put("43", "湖南");
|
||||||
|
PROVINCE_CODES.put("44", "广东");
|
||||||
|
PROVINCE_CODES.put("45", "广西");
|
||||||
|
PROVINCE_CODES.put("46", "海南");
|
||||||
|
PROVINCE_CODES.put("50", "重庆");
|
||||||
|
PROVINCE_CODES.put("51", "四川");
|
||||||
|
PROVINCE_CODES.put("52", "贵州");
|
||||||
|
PROVINCE_CODES.put("53", "云南");
|
||||||
|
PROVINCE_CODES.put("54", "西藏");
|
||||||
|
PROVINCE_CODES.put("61", "陕西");
|
||||||
|
PROVINCE_CODES.put("62", "甘肃");
|
||||||
|
PROVINCE_CODES.put("63", "青海");
|
||||||
|
PROVINCE_CODES.put("64", "宁夏");
|
||||||
|
PROVINCE_CODES.put("65", "新疆");
|
||||||
|
PROVINCE_CODES.put("71", "台湾");
|
||||||
|
PROVINCE_CODES.put("81", "香港");
|
||||||
|
PROVINCE_CODES.put("82", "澳门");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String idCard = ((String) value).toUpperCase();
|
||||||
|
|
||||||
|
// 长度校验
|
||||||
|
if (idCard.length() != 15 && idCard.length() != 18) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式校验
|
||||||
|
if (idCard.length() == 15) {
|
||||||
|
return validate15IdCard(idCard);
|
||||||
|
} else {
|
||||||
|
return validate18IdCard(idCard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验15位身份证
|
||||||
|
*/
|
||||||
|
private boolean validate15IdCard(String idCard) {
|
||||||
|
// 15位身份证格式:省(2位)市(2位)县(2位)年(2位)月(2位)日(2位)顺序号(3位)
|
||||||
|
if (!Pattern.matches("^\\d{15}$", idCard)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省份代码校验
|
||||||
|
String provinceCode = idCard.substring(0, 2);
|
||||||
|
if (!PROVINCE_CODES.containsKey(provinceCode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 出生日期校验
|
||||||
|
String year = "19" + idCard.substring(6, 8);
|
||||||
|
String month = idCard.substring(8, 10);
|
||||||
|
String day = idCard.substring(10, 12);
|
||||||
|
|
||||||
|
return validateDate(year, month, day);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验18位身份证
|
||||||
|
*/
|
||||||
|
private boolean validate18IdCard(String idCard) {
|
||||||
|
// 18位身份证格式:省(2位)市(2位)县(2位)年(4位)月(2位)日(2位)顺序号(3位)校验码(1位)
|
||||||
|
if (!Pattern.matches("^\\d{17}[0-9Xx]$", idCard)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省份代码校验
|
||||||
|
String provinceCode = idCard.substring(0, 2);
|
||||||
|
if (!PROVINCE_CODES.containsKey(provinceCode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 出生日期校验
|
||||||
|
String year = idCard.substring(6, 10);
|
||||||
|
String month = idCard.substring(10, 12);
|
||||||
|
String day = idCard.substring(12, 14);
|
||||||
|
|
||||||
|
if (!validateDate(year, month, day)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验码校验
|
||||||
|
return validateCheckCode(idCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验日期是否合法
|
||||||
|
*/
|
||||||
|
private boolean validateDate(String year, String month, String day) {
|
||||||
|
try {
|
||||||
|
int y = Integer.parseInt(year);
|
||||||
|
int m = Integer.parseInt(month);
|
||||||
|
int d = Integer.parseInt(day);
|
||||||
|
|
||||||
|
// 年份范围:1900-当前年份
|
||||||
|
int currentYear = java.time.Year.now().getValue();
|
||||||
|
if (y < 1900 || y > currentYear) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 月份范围:1-12
|
||||||
|
if (m < 1 || m > 12) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期范围
|
||||||
|
int[] daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
|
// 闰年2月29天
|
||||||
|
if (isLeapYear(y)) {
|
||||||
|
daysInMonth[1] = 29;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d >= 1 && d <= daysInMonth[m - 1];
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 判断是否为闰年
|
||||||
|
*/
|
||||||
|
private boolean isLeapYear(int year) {
|
||||||
|
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验18位身份证的校验码
|
||||||
|
*/
|
||||||
|
private boolean validateCheckCode(String idCard) {
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < 17; i++) {
|
||||||
|
sum += (idCard.charAt(i) - '0') * WEIGHT[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char checkCode = VALIDATE_CODE[sum % 11];
|
||||||
|
return checkCode == idCard.charAt(17);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return "请输入有效的身份证号码(15位或18位)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "身份证号码校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 密码校验方法
|
||||||
|
* @filename PasswordValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class PasswordValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
private final int minLength;
|
||||||
|
private final int maxLength;
|
||||||
|
private final boolean requireUpperCase;
|
||||||
|
private final boolean requireLowerCase;
|
||||||
|
private final boolean requireDigit;
|
||||||
|
private final boolean requireSpecialChar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 默认密码规则:6-20位,必须包含字母和数字
|
||||||
|
*/
|
||||||
|
public PasswordValidateMethod() {
|
||||||
|
this(6, 20, false, false, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 自定义密码规则
|
||||||
|
* @param minLength 最小长度
|
||||||
|
* @param maxLength 最大长度
|
||||||
|
* @param requireUpperCase 是否需要大写字母
|
||||||
|
* @param requireLowerCase 是否需要小写字母
|
||||||
|
* @param requireDigit 是否需要数字
|
||||||
|
* @param requireSpecialChar 是否需要特殊字符
|
||||||
|
*/
|
||||||
|
public PasswordValidateMethod(int minLength, int maxLength,
|
||||||
|
boolean requireUpperCase, boolean requireLowerCase,
|
||||||
|
boolean requireDigit, boolean requireSpecialChar) {
|
||||||
|
this.minLength = minLength;
|
||||||
|
this.maxLength = maxLength;
|
||||||
|
this.requireUpperCase = requireUpperCase;
|
||||||
|
this.requireLowerCase = requireLowerCase;
|
||||||
|
this.requireDigit = requireDigit;
|
||||||
|
this.requireSpecialChar = requireSpecialChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String password = (String) value;
|
||||||
|
|
||||||
|
// 长度校验
|
||||||
|
if (password.length() < minLength || password.length() > maxLength) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 大写字母校验
|
||||||
|
if (requireUpperCase && !Pattern.compile("[A-Z]").matcher(password).find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 小写字母校验
|
||||||
|
if (requireLowerCase && !Pattern.compile("[a-z]").matcher(password).find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数字校验
|
||||||
|
if (requireDigit && !Pattern.compile("[0-9]").matcher(password).find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 特殊字符校验
|
||||||
|
if (requireSpecialChar && !Pattern.compile("[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/?]").matcher(password).find()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
StringBuilder msg = new StringBuilder("密码必须是");
|
||||||
|
msg.append(minLength).append("-").append(maxLength).append("位");
|
||||||
|
|
||||||
|
if (requireUpperCase || requireLowerCase || requireDigit || requireSpecialChar) {
|
||||||
|
msg.append(",且包含");
|
||||||
|
boolean first = true;
|
||||||
|
|
||||||
|
if (requireUpperCase) {
|
||||||
|
msg.append("大写字母");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (requireLowerCase) {
|
||||||
|
if (!first) msg.append("、");
|
||||||
|
msg.append("小写字母");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (requireDigit) {
|
||||||
|
if (!first) msg.append("、");
|
||||||
|
msg.append("数字");
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (requireSpecialChar) {
|
||||||
|
if (!first) msg.append("、");
|
||||||
|
msg.append("特殊字符");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "密码校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 手机号码校验方法
|
||||||
|
* @filename PhoneValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class PhoneValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
// 中国大陆手机号正则
|
||||||
|
private static final Pattern CHINA_PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
|
||||||
|
|
||||||
|
// 香港手机号正则
|
||||||
|
private static final Pattern HK_PHONE_PATTERN = Pattern.compile("^[5-9]\\d{7}$");
|
||||||
|
|
||||||
|
// 台湾手机号正则
|
||||||
|
private static final Pattern TW_PHONE_PATTERN = Pattern.compile("^09\\d{8}$");
|
||||||
|
|
||||||
|
private final boolean strictMode; // 严格模式,只验证中国大陆手机号
|
||||||
|
|
||||||
|
public PhoneValidateMethod() {
|
||||||
|
this.strictMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PhoneValidateMethod(boolean strictMode) {
|
||||||
|
this.strictMode = strictMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String phone = (String) value;
|
||||||
|
|
||||||
|
// 去除空格和横线
|
||||||
|
phone = phone.replaceAll("[\\s-]", "");
|
||||||
|
|
||||||
|
if (strictMode) {
|
||||||
|
// 严格模式:只验证中国大陆手机号
|
||||||
|
return CHINA_PHONE_PATTERN.matcher(phone).matches();
|
||||||
|
} else {
|
||||||
|
// 宽松模式:支持大陆、香港、台湾手机号
|
||||||
|
return CHINA_PHONE_PATTERN.matcher(phone).matches()
|
||||||
|
|| HK_PHONE_PATTERN.matcher(phone).matches()
|
||||||
|
|| TW_PHONE_PATTERN.matcher(phone).matches();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return strictMode ? "请输入有效的手机号码" : "请输入有效的手机号码(支持大陆、香港、台湾)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "手机号码校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description URL校验方法
|
||||||
|
* @filename UrlValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public class UrlValidateMethod implements ValidateMethod {
|
||||||
|
|
||||||
|
// URL正则表达式
|
||||||
|
private static final Pattern URL_PATTERN = Pattern.compile(
|
||||||
|
"^(https?|ftp)://[a-zA-Z0-9+&@#/%?=~_|!:,.;-]*[a-zA-Z0-9+&@#/%=~_|-]$"
|
||||||
|
);
|
||||||
|
|
||||||
|
private final boolean requireHttps; // 是否要求HTTPS
|
||||||
|
|
||||||
|
public UrlValidateMethod() {
|
||||||
|
this.requireHttps = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UrlValidateMethod(boolean requireHttps) {
|
||||||
|
this.requireHttps = requireHttps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(Object value) {
|
||||||
|
if (value == null || !(value instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = ((String) value).trim();
|
||||||
|
|
||||||
|
// 基本格式校验
|
||||||
|
if (!URL_PATTERN.matcher(url).matches()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPS校验
|
||||||
|
if (requireHttps && !url.startsWith("https://")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return requireHttps ? "请输入有效的HTTPS链接" : "请输入有效的URL";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "URL校验";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法接口,定义不同类型的校验方式
|
||||||
|
* @filename ValidateMethod.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public interface ValidateMethod {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法
|
||||||
|
* @param value 待校验的值
|
||||||
|
* @return boolean 是否校验通过
|
||||||
|
*/
|
||||||
|
boolean validate(Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取校验失败的错误提示信息
|
||||||
|
* @return String 错误提示信息
|
||||||
|
*/
|
||||||
|
String getErrorMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取校验方法的名称
|
||||||
|
* @return String 校验方法名称
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
package org.xyzh.common.utils.validation.method;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 校验方法类型枚举
|
||||||
|
* @filename ValidateMethodType.java
|
||||||
|
* @author yslg
|
||||||
|
* @copyright xyzh
|
||||||
|
* @since 2025-10-16
|
||||||
|
*/
|
||||||
|
public enum ValidateMethodType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码校验(默认:6-20位,必须包含字母和数字)
|
||||||
|
*/
|
||||||
|
PASSWORD("密码校验", PasswordValidateMethod.class, PasswordValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强密码校验(8-20位,必须包含大小写字母、数字和特殊字符)
|
||||||
|
*/
|
||||||
|
STRONG_PASSWORD("强密码校验", PasswordValidateMethod.class,
|
||||||
|
() -> new PasswordValidateMethod(8, 20, true, true, true, true)),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证号校验(支持15位和18位)
|
||||||
|
*/
|
||||||
|
ID_CARD("身份证号校验", IdCardValidateMethod.class, IdCardValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码校验(中国大陆)
|
||||||
|
*/
|
||||||
|
PHONE("手机号码校验", PhoneValidateMethod.class, PhoneValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号码校验(宽松模式,支持大陆、香港、台湾)
|
||||||
|
*/
|
||||||
|
PHONE_LOOSE("手机号码校验(宽松)", PhoneValidateMethod.class,
|
||||||
|
() -> new PhoneValidateMethod(false)),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱地址校验
|
||||||
|
*/
|
||||||
|
EMAIL("邮箱地址校验", EmailValidateMethod.class, EmailValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL链接校验
|
||||||
|
*/
|
||||||
|
URL("URL链接校验", UrlValidateMethod.class, UrlValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTPS链接校验
|
||||||
|
*/
|
||||||
|
HTTPS_URL("HTTPS链接校验", UrlValidateMethod.class,
|
||||||
|
() -> new UrlValidateMethod(true)),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 银行卡号校验
|
||||||
|
*/
|
||||||
|
BANK_CARD("银行卡号校验", BankCardValidateMethod.class, BankCardValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文字符校验(纯中文)
|
||||||
|
*/
|
||||||
|
CHINESE("中文字符校验", ChineseValidateMethod.class, ChineseValidateMethod::new),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中文字符校验(允许标点符号)
|
||||||
|
*/
|
||||||
|
CHINESE_WITH_PUNCTUATION("中文字符校验(含标点)", ChineseValidateMethod.class,
|
||||||
|
() -> new ChineseValidateMethod(true));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验方法名称
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验方法实现类
|
||||||
|
*/
|
||||||
|
private final Class<? extends ValidateMethod> methodClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验方法实例提供者
|
||||||
|
*/
|
||||||
|
private final Supplier<ValidateMethod> methodSupplier;
|
||||||
|
|
||||||
|
ValidateMethodType(String name, Class<? extends ValidateMethod> methodClass,
|
||||||
|
Supplier<ValidateMethod> methodSupplier) {
|
||||||
|
this.name = name;
|
||||||
|
this.methodClass = methodClass;
|
||||||
|
this.methodSupplier = methodSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取校验方法名称
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 获取校验方法实现类
|
||||||
|
* @return Class
|
||||||
|
*/
|
||||||
|
public Class<? extends ValidateMethod> getMethodClass() {
|
||||||
|
return methodClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 创建校验方法实例
|
||||||
|
* @return ValidateMethod
|
||||||
|
*/
|
||||||
|
public ValidateMethod createInstance() {
|
||||||
|
return methodSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据名称获取枚举
|
||||||
|
* @param name 名称
|
||||||
|
* @return ValidateMethodType
|
||||||
|
*/
|
||||||
|
public static ValidateMethodType fromName(String name) {
|
||||||
|
for (ValidateMethodType type : values()) {
|
||||||
|
if (type.getName().equals(name)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user