This commit is contained in:
2025-12-18 16:48:45 +08:00
parent b97f0da746
commit 41cbe2bd54
80 changed files with 5434 additions and 351 deletions

View File

@@ -1,23 +0,0 @@
package org.xyzh.common.utils;
import java.util.UUID;
/**
* @description IDUtils.java文件描述
* @filename IDUtils.java
* @author yslg
* @copyright yslg
* @since 2025-11-02
*/
public class IDUtils {
/**
* @description 生成UUID
* @return UUID
* @author yslg
* @since 2025-11-02
*/
public static String generateID() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
}

View File

@@ -0,0 +1,46 @@
package org.xyzh.common.utils.id;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
/**
* @description ID生成工具类
* @filename IdUtil.java
* @author yslg
* @copyright xyzh
* @since 2025-12-17
*/
public class IdUtil {
private static final AtomicLong SEQUENCE = new AtomicLong(0);
/**
* 生成流水号UUID格式无横线
*/
public static String getOptsn() {
return "optsn"+UUID.randomUUID().toString().replaceAll("-", "");
}
/**
* 生成雪花ID简化实现使用时间戳+序列号)
*/
public static String getSnowflakeId() {
long timestamp = System.currentTimeMillis();
long seq = SEQUENCE.incrementAndGet() % 10000;
return String.valueOf(timestamp) + String.format("%04d", seq);
}
/**
* 生成UUID
*/
public static String generateUUID() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
/**
* 生成ID
*/
public static String generateID() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
}

View File

@@ -1,8 +1,13 @@
package org.xyzh.common.utils.validation;
import org.xyzh.common.utils.validation.method.InSetValidateMethod;
import org.xyzh.common.utils.validation.method.MinFieldsValidateMethod;
import org.xyzh.common.utils.validation.method.ObjectValidateMethod;
import org.xyzh.common.utils.validation.method.ValidateMethod;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@@ -37,10 +42,10 @@ public class ValidationUtils {
for (ValidationParam param : validationParams) {
try {
Object fieldValue = getFieldValue(obj, param.getFieldName());
validateField(param, fieldValue, result);
validateField(param, fieldValue, obj, result);
} catch (Exception e) {
result.addError(param.getFieldLabel() + "字段获取失败: " + e.getMessage());
}
}
}
return result;
@@ -52,7 +57,7 @@ public class ValidationUtils {
* @param validationParams 校验参数列表
* @return ValidationResult 校验结果
*/
public static ValidationResult validateMap(Map<String, Object> map, List<ValidationParam> validationParams) {
public static <V> ValidationResult validateMap(Map<String, V> map, List<ValidationParam> validationParams) {
ValidationResult result = new ValidationResult();
if (map == null) {
@@ -66,7 +71,7 @@ public class ValidationUtils {
for (ValidationParam param : validationParams) {
Object fieldValue = map.get(param.getFieldName());
validateField(param, fieldValue, result);
validateField(param, fieldValue, map, result);
}
return result;
@@ -76,9 +81,10 @@ public class ValidationUtils {
* @description 校验单个字段
* @param param 校验参数
* @param fieldValue 字段值
* @param obj 原始对象
* @param result 校验结果
*/
private static void validateField(ValidationParam param, Object fieldValue, ValidationResult result) {
private static void validateField(ValidationParam param, Object fieldValue, Object obj, ValidationResult result) {
String fieldLabel = param.getFieldLabel();
// 1. 必填校验
@@ -176,10 +182,11 @@ public class ValidationUtils {
}
}
// 8. 使用ValidateMethod校验直接传入实例,保留兼容性
// 8. 使用ValidateMethod校验直接传入实例
if (param.getValidateMethod() != null) {
try {
if (!param.getValidateMethod().validate(fieldValue)) {
Object validateTarget = (param.getValidateMethod() instanceof ObjectValidateMethod) ? obj : fieldValue;
if (!param.getValidateMethod().validate(validateTarget)) {
String errorMsg = param.getValidateMethod().getErrorMessage();
if (errorMsg != null && !errorMsg.isEmpty()) {
result.addError(errorMsg);
@@ -194,13 +201,27 @@ public class ValidationUtils {
}
/**
* @description 获取对象字段值支持getter方法直接访问)
* @description 获取对象字段值支持getter方法直接访问和嵌套路径
* @param obj 对象
* @param fieldName 字段名
* @param fieldName 字段名,支持嵌套路径如"pageParam.page"
* @return 字段值
* @throws Exception 异常
*/
private static Object getFieldValue(Object obj, String fieldName) throws Exception {
if (obj == null) {
return null;
}
// 支持嵌套路径,如"pageParam.page"
if (fieldName.contains(".")) {
String[] parts = fieldName.split("\\.", 2);
Object nestedObj = getFieldValue(obj, parts[0]);
if (nestedObj == null) {
return null;
}
return getFieldValue(nestedObj, parts[1]);
}
if (obj instanceof Map) {
return ((Map<?, ?>) obj).get(fieldName);
}
@@ -317,5 +338,46 @@ public class ValidationUtils {
.patternDesc("请输入有效的手机号码")
.build();
}
}
/**
* @description 创建"至少填一个"校验参数
* @param fieldNames 字段名列表
* @param fieldLabels 字段标签列表
* @return ValidationParam
*/
public static ValidationParam atLeastOne(List<String> fieldNames, List<String> fieldLabels) {
return minFields(fieldNames, fieldLabels, 1);
}
/**
* @description 创建"至少填几个"校验参数
* @param fieldNames 字段名列表
* @param fieldLabels 字段标签列表
* @param minCount 至少填写的数量
* @return ValidationParam
*/
public static ValidationParam minFields(List<String> fieldNames, List<String> fieldLabels, int minCount) {
return ValidationParam.builder()
.fieldName("_minFields")
.fieldLabel(String.join("", fieldLabels))
.validateMethod(new MinFieldsValidateMethod(fieldNames, fieldLabels, minCount))
.build();
}
/**
* @description 创建N选1校验参数值必须是集合中的一个
* @param fieldName 字段名
* @param fieldLabel 字段标签
* @param required 是否必填
* @param allowedValues 允许的值集合
* @return ValidationParam
*/
public static ValidationParam inSet(String fieldName, String fieldLabel, Boolean required, Collection<?> allowedValues) {
return ValidationParam.builder()
.fieldName(fieldName)
.fieldLabel(fieldLabel)
.required(required)
.validateMethod(new InSetValidateMethod(fieldLabel, allowedValues))
.build();
}
}

View File

@@ -0,0 +1,68 @@
package org.xyzh.common.utils.validation.method;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @description N选1校验方法值必须是指定集合中的一个
* @filename InSetValidateMethod.java
* @author yslg
* @copyright xyzh
* @since 2025-12-18
*/
public class InSetValidateMethod implements ValidateMethod {
private final Set<Object> allowedValues;
private final String errorMessage;
/**
* @description 构造函数
* @param fieldLabel 字段标签
* @param allowedValues 允许的值集合
*/
public InSetValidateMethod(String fieldLabel, Collection<?> allowedValues) {
this.allowedValues = allowedValues.stream().map(v -> (Object) v).collect(Collectors.toSet());
this.errorMessage = fieldLabel + "必须是以下值之一: " + formatValues(allowedValues);
}
/**
* @description 构造函数(自定义错误信息)
* @param fieldLabel 字段标签
* @param allowedValues 允许的值集合
* @param customErrorMessage 自定义错误信息
*/
public InSetValidateMethod(String fieldLabel, Collection<?> allowedValues, String customErrorMessage) {
this.allowedValues = allowedValues.stream().map(v -> (Object) v).collect(Collectors.toSet());
this.errorMessage = customErrorMessage;
}
@Override
public Boolean validate(Object value) {
if (value == null) {
return false;
}
return allowedValues.contains(value);
}
@Override
public String getErrorMessage() {
return errorMessage;
}
@Override
public String getName() {
return "N选1校验";
}
/**
* @description 格式化允许值列表
* @param values 值集合
* @return 格式化后的字符串
*/
private String formatValues(Collection<?> values) {
return values.stream()
.map(v -> v instanceof String ? "\"" + v + "\"" : String.valueOf(v))
.collect(Collectors.joining(", ", "[", "]"));
}
}

View File

@@ -0,0 +1,98 @@
package org.xyzh.common.utils.validation.method;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
/**
* @description 至少填几个字段校验方法
* @filename MinFieldsValidateMethod.java
* @author yslg
* @copyright yslg
* @since 2025-12-18
*/
public class MinFieldsValidateMethod implements ObjectValidateMethod {
private final List<String> fieldNames;
private final int minCount;
private final String errorMessage;
public MinFieldsValidateMethod(List<String> fieldNames, List<String> fieldLabels) {
this(fieldNames, fieldLabels, 1);
}
public MinFieldsValidateMethod(List<String> fieldNames, List<String> fieldLabels, int minCount) {
this.fieldNames = fieldNames;
this.minCount = minCount;
this.errorMessage = String.join("", fieldLabels) + "至少填写" + minCount + "";
}
@Override
public Boolean validate(Object obj) {
if (obj == null || fieldNames == null || fieldNames.isEmpty()) {
return false;
}
int count = 0;
for (String fieldName : fieldNames) {
try {
Object fieldValue = getFieldValue(obj, fieldName);
if (fieldValue != null) {
if (fieldValue instanceof String) {
if (!((String) fieldValue).trim().isEmpty()) {
count++;
}
} else {
count++;
}
}
} catch (Exception e) {
// 字段不存在,忽略
}
}
return count >= minCount;
}
private 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);
Method getter = clazz.getMethod(getterName);
return getter.invoke(obj);
} catch (NoSuchMethodException e) {
// 尝试直接访问字段
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;
}
}
}
@Override
public String getErrorMessage() {
return errorMessage;
}
@Override
public String getName() {
return "至少填" + minCount + "个校验";
}
}

View File

@@ -0,0 +1,11 @@
package org.xyzh.common.utils.validation.method;
/**
* @description 对象级校验方法接口,表示对整个对象进行校验
* @filename ObjectValidateMethod.java
* @author yslg
* @copyright yslg
* @since 2025-12-18
*/
public interface ObjectValidateMethod extends ValidateMethod {
}