easyexcel导入注解校验
package com.ruoyi.system.service.imports;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.system.service.imports.valid.EnumValidator;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.lang.reflect.Field;
import java.util.Set;
/**
* @date :Created 2022/12/28 13:00
* @description :校验工具
*/
public class EasyExcelValidHelper {
private EasyExcelValidHelper() {
}
/**
* 校验常量
*/
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
/**
* description 对象校验
*
* @param entity 导入数据
* @return java.lang.String
**/
public static <T> String validateEntity(T entity) throws NoSuchFieldException {
StringBuilder result = new StringBuilder();
Set<ConstraintViolation<T>> set = VALIDATOR.validate(entity, Default.class);
if (set != null && !set.isEmpty()) {
for (ConstraintViolation<T> cv : set) {
Field declaredField = entity.getClass().getDeclaredField(cv.getPropertyPath().toString());
ExcelProperty annotation = declaredField.getAnnotation(ExcelProperty.class);
result.append(annotation.value()[0]).append(cv.getMessage()).append("; ");
}
}
return result.toString();
}
}
枚举校验
package com.ruoyi.system.service.imports.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* @date :Created 2022/12/28 13:00
* @description :校验枚举注解
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumValidator.class)
public @interface EnumValid {
/**
* 枚举的类型
*/
Class<?> value();
/**
* 错误消息
*
* @return
*/
String message() default "枚举类型的值不正确";
/**
* 获取枚举值的方法
*/
String method() default "getCode";
String method2() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
package com.ruoyi.system.service.imports.valid;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* @date :Created 2022/12/28 14:40
* @description :枚举验证
*/
public class EnumValidator implements ConstraintValidator<EnumValid, Object> {
private static final Logger logger = LoggerFactory.getLogger(EnumValidator.class);
/**
* 存具体枚举的值
*/
private final List<Object> values = Lists.newArrayList();
@Override
public void initialize(EnumValid constraintAnnotation) {
Class<?> enumClazz = constraintAnnotation.value();
Object[] enumConstants = enumClazz.getEnumConstants();
if (null == enumConstants) {
return;
}
Method method = BeanUtils.findMethod(enumClazz, constraintAnnotation.method());
if (null == method) {
logger.warn("枚举对象:[{}]中不存在方法:[{}],请检查.", enumClazz.getName(), constraintAnnotation.method());
throw new RuntimeException("枚举对象中不存在获取值的方法");
}
method.setAccessible(true);
try {
for (Object enumConstant : enumConstants) {
values.add(method.invoke(enumConstant));
}
} catch (IllegalAccessException | InvocationTargetException e) {
logger.warn("获取枚举类:[{}]的枚举对象的值失败.", enumClazz);
throw new RuntimeException("获取枚举值失败");
}
Method method2 = BeanUtils.findMethod(enumClazz, constraintAnnotation.method2());
if (null != method2) {
// method2.setAccessible(true);
try {
for (Object enumConstant : enumConstants) {
values.add(method2.invoke(enumConstant));
}
} catch (IllegalAccessException | InvocationTargetException e) {
logger.warn("获取枚举类:[{}]的枚举对象的值失败.", enumClazz);
throw new RuntimeException("获取枚举值失败");
}
}
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return null == value || values.contains(value);
}
}
package com.ruoyi.system.domain.imports;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.ruoyi.system.domain.enums.AppLoginTypeEnum;
import com.ruoyi.system.domain.export.BaseExportData;
import com.ruoyi.system.service.imports.valid.EnumValid;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/**
* 应用导入数据类
**/
public class AppCfgExcelData extends BaseExportData {
@Length(max=20)
@NotBlank(message = "不可空")
@ColumnWidth(20)
@ExcelProperty("应用ID")
private String appId;
@NotBlank(message = "不可空")
@ColumnWidth(20)
@ExcelProperty("应用名称")
private String appName;
@NotBlank(message = "不可空")
@ColumnWidth(20)
@ExcelProperty("应用类型")
private String appTypeName;
@NotBlank(message = "不可空")
@ColumnWidth(20)
@ExcelProperty("应用子类型")
private String appSubtypeName;
@EnumValid(value = AppLoginTypeEnum.class, method2 = "getName", message = "值不正确")
@NotBlank(message = "不可空")
@ColumnWidth(10)
@ExcelProperty("登录类型")
private String loginTypeName;
@NotBlank(message = "不可空")
@ColumnWidth(10)
@ExcelProperty("发布状态")
private String releaseStateName;
@NotBlank(message = "不可空")
@ColumnWidth(10)
@ExcelProperty("显示顺序")
private String orderNum;
/**
* 错误信息
*/
@ExcelProperty("错误描述")
private String error;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getAppTypeName() {
return appTypeName;
}
public void setAppTypeName(String appTypeName) {
this.appTypeName = appTypeName;
}
public String getAppSubtypeName() {
return appSubtypeName;
}
public void setAppSubtypeName(String appSubtypeName) {
this.appSubtypeName = appSubtypeName;
}
public String getLoginTypeName() {
return loginTypeName;
}
public void setLoginTypeName(String loginTypeName) {
this.loginTypeName = loginTypeName;
}
public String getReleaseStateName() {
return releaseStateName;
}
public void setReleaseStateName(String releaseStateName) {
this.releaseStateName = releaseStateName;
}
public String getOrderNum() {
return orderNum;
}
public void setOrderNum(String orderNum) {
this.orderNum = orderNum;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
}
// 校验
for (AppCfgExcelData excelDatum : excelData) {
try {
String errorMsg = EasyExcelValidHelper.validateEntity(excelDatum);
logger.error("errorMsg:{}", errorMsg);
excelDatum.setError(errorMsg);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
空和非空检查: @Null、@NotNull、@NotBlank、@NotEmpty
注解 支持Java类型 备注
@Null Object 验证元素值为null
@NotNull Object 验证元素值不能为 null
@NotBlank CharSequence 验证元素值不为null且移除两边空格后长度大于0
@NotEmpty CharSequence,Collection,Map and Arrays 验证元素值不为null且不为空(字符串长度不为0、集合大小不为0)
Boolean值检查: @AssertTrue、@AssertFalse
注解 支持Java类型 备注
@AssertTrue Boolean, boolean 验证元素值必须为true,否则抛异常
@AssertFalse Boolean, boolean 验证元素值必须为flase
长度检查: @Size、@Length
注解 支持Java类型 备注
@Size String,Collection,Map,arrays,CharSequence 验证元素个数包含在一个区间
@Length CharSequence 验证元素值包含在一个区间
日期检查: @Future、@FutureOrPresent、@Past、@PastOrPresent
注解 支持Java类型 备注
@Future java.util.Date, java.util.Calendar 验证日期为当前时间之后
@FutureOrPresent java.util.Date, java.util.Calendar 验证日期为当前时间或之后一个时间
@Past java.util.Date, java.util.Calendar 验证日期为当前时间之前
@PastOrPresent java.util.Date, java.util.Calendar 验证日期为当前时间或之前
其它检查: @Email、@CreditCardNumber、@URL、@Pattern、@ScriptAssert、@UniqueElements
注解 支持Java类型 备注
@Email CharSequence 验证日期为当前时间之后
@CreditCardNumber CharSequence 验证日期为当前时间或之后一个时间
@URL CharSequence 验证日期为当前时间之前
@Pattern CharSequence 验证日期为当前时间或之前
@Valid Object 验证关联对象元素进行递归校验检查
@UniqueElements Collection 校验集合中的元素必须保持唯一 否则异常
数值检查: @Min、@Max、@Range、@DecimalMin、@DecimalMax、@Digits
注解 支持Java类型 备注
@Min BigDecimal, BigInteger, byte, short,int, long,Number. 检验当前数值大于等于指定值
@Max CharSequence 检验当前数值小于等于指定值
@Range CharSequence 验证数值为指定值区间范围内
@DecimalMin CharSequence 验证数值是否大于等于指定值
@DecimalMax Object 验证数值是否小于等于指定值
@Digits(integer = 3, fraction = 2) 验证注解的元素值的整数位数和小数位数上限
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)