自定义注解实现excel导入数据参数校验

一 自定义注解

1.元注解

我们在自定义的注解上要添加几个元注解

@Target
@Retention
@Inherited
@Documented

1.1简单介绍

@Target
用来声明当前注解可以使用的位置

value描述
ElementType.TYPE应用于类、接口(包括注解类型)、枚举
ElementType.FIELD应用于属性(包括枚举中的常量)
ElementType.METHOD应用于方法
ElementType.PARAMETER应用于方法的形参
ElementType.CONSTRUCTOR应用于构造函数
ElementType.LOCAL_VARIABLE应用于局部变量
ElementType.ANNOTATION_TYPE应用于注解类型
ElementType.PACKAGE应用于包
ElementType.TYPE_PARAMETER应用于类型变量
ElementType.TYPE_USE应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

@Retention
表明该注解的生命周期

生命周期类型描述
RetentionPolicy.SOURCE编译时被丢弃,不包含在类文件中
RetentionPolicy.CLASSJVM加载时被丢弃,包含在类文件中,默认值
RetentionPolicy.RUNTIME由JVM 加载,包含在类文件中,在运行时可以被获取到

@Inherited
表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解。

@Document
表明该注解标记的元素可以被Javadoc 或类似的工具文档化。

一般声明自定义注解的时候 使用前三个就够了

2 声明注解

// {} 中可以声明多个Target类型, 这个注解我们只用在类的属性上, 只注明这一个值即可
@Target({ElementType.FIELD})
// 在运行时使用
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelValid {
// 注解的属性 
// 属性声明格式 :   数据类型  属性名()  default  默认值;
// 在调用获取属性值的时候  直接通过 ' 注解对象.属性名()' 的形式
	int length() default 0;
	DataTypeEnum type() default DataTypeEnum.String;
	boolean notNull() default true;

	String lengthMessage() default "";
	String typeMessage() default "";
	String notNullMessage() default "";
}

枚举类

public enum DataTypeEnum {
	Byte("Byte"),
	Short("Short"),
	Integer("Integer"),
	Long("Long"),
	Float("Float"),
	Double("Double"),
	String("String"),
	BigDecimal("BigDecimal"),
	Boolean("Boolean");


	private final String value;

	private DataTypeEnum(String value) {
		this.value = value;
	}

	public String value() {
		return this.value;
	}

这样注解就声明好了

二 校验工具类

编写校验工具类

/**
 * 导入excel参数校验
 */
public class ExcelValidUtil {

	/**
	 * Excel导入字段校验
	 *
	 * @param object 校验的JavaBean 其属性须有自定义注解
	 */
	public static void Excelvalid(Object object) throws RuntimeException {
			valid(object,0);
	}
	
	public static void Excelvalid(Object object, int size) throws RuntimeException {
		valid(object,size);
	}
	
	private static void valid(Object object,int size) throws RuntimeException {
		String prefix = "";
		if (size > 0) {
			prefix = "第" + size + "条数据";
		}
		// 通过反射获取类的所有属性字段
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			//设置可访问
			field.setAccessible(true);
			// 进行判断 如果属性上有 @ExcelIgnore 注解或者没有 @ExcelProperty则表示该字段不参数映射, 跳过
			if (field.isAnnotationPresent(ExcelIgnore.class) || !field.isAnnotationPresent(ExcelProperty.class)) {
				continue;
			}

			//属性的值
			Object fieldValue = null;
			try {
				fieldValue = field.get(object);
			} catch (IllegalAccessException e) {
				throw new RuntimeException("导入参数检查失败");
			}


			//是否包含自定义校验注解
			boolean hasValid = field.isAnnotationPresent(ExcelValid.class);
			if (hasValid ) {
			// 获取自定义注解
				ExcelValid annotation = field.getAnnotation(ExcelValid.class);
				// 非空校验
				boolean notNull = annotation.notNull(); // 获取注解notNull属性的值
				if (notNull && Objects.isNull(fieldValue)) {
					throw new RuntimeException(prefix + " " +annotation.notNullMessage());
				}
				// 类型校验
				DataTypeEnum type = annotation.type(); // 获取注解type属性的值
				if (!validType(type,fieldValue)) {
					throw new RuntimeException(prefix + " " +annotation.typeMessage());
				}
				// 长度校验
				int length = annotation.length(); // 获取注解length属性的值
				if (length > 0) {
					if (length < String.valueOf(fieldValue).length()) {
						throw new RuntimeException(prefix + " " +annotation.lengthMessage());
					}
				}
			}

		}
	}
	// 类型转换校验
	private static Boolean validType(DataTypeEnum type,Object fieldValue) {
		try {
			switch (type){
				case Byte: Byte.valueOf(String.valueOf(fieldValue)); break;
				case Short: Short.valueOf(String.valueOf(fieldValue)); break;
				case Integer: Integer.valueOf(String.valueOf(fieldValue)); break;
				case Long: Long.valueOf(String.valueOf(fieldValue)); break;
				case Float: Float.valueOf(String.valueOf(fieldValue)); break;
				case Double: Double.valueOf(String.valueOf(fieldValue)); break;
				case String: String.valueOf(fieldValue); break;
				case BigDecimal: new BigDecimal(String.valueOf(fieldValue)); break;
				case Boolean: Boolean.valueOf(String.valueOf(fieldValue)); break;
				default: break;
			}
		}catch (Exception e){
		// 转换失败返回false
			return false;
		}
		return true;
	}
}

三 进行校验

3.1 在excel模板中使用 自定义注解

@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class GoodsExcel implements Serializable {
	private static final long serialVersionUID = 1L;


	@ExcelProperty("租户编号(可空)")
	@ExcelValid(length = 255,lengthMessage = "分类编号 过长",
	notNull = false,
	type = DataTypeEnum.String,typeMessage = "分类编号 数据格式异常")
	private String tenantId;

// 其中notnull 默认值是 true, 可空字段要填成 false
// type 默认类型是string,   可省略不写

// 默认值信息可省略
	@ExcelProperty("货品名称")
	@ExcelValid(length = 255,lengthMessage = "货品名称 过长",
		notNullMessage = "货品名称 不可为空"
	)
	private String goodsName;

// 没有 ExcelProperty 注解 不会校验该字段
	@ColumnWidth(30)
	@ExcelValid(length = 2,lengthMessage = "是否一物一码 过长",
		notNullMessage = "是否一物一码 不可为空"
	)
	private String isNotEditStr;

// 有ExcelIgnore注解 不会校验该字段
	@ExcelProperty("是否一物一码(是/否)")
	@ExcelIgnore
	private Integer isNotEdit;

}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的自定义注解是一种给代码提供额外信息的方式,可以在运行时通过反射机制获取注解的信息。通过自定义注解,我们可以实现参数校验,提高代码的健壮性和可维护性。 首先,我们需要定义一个注解类,用于定义参数校验的规则。比如,我们可以定义一个注解叫做@ParamCheck,用于对方法的参数进行校验。 ```java @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface ParamCheck { String value(); } ``` 接着,在需要进行参数校验的方法上使用@ParamCheck注解,并给注解传入校验规则的表达式。比如,我们可以给一个名为checkNumber的方法的参数添加校验注解。 ```java public void checkNumber(@ParamCheck("number > 0") int number) { // ... } ``` 然后,在方法内部,通过反射机制获取参数的注解信息,并根据注解中定义的校验规则对参数进行校验。 ```java public void checkNumber(int number) { Parameter parameter = ...; // 获取方法的参数信息 ParamCheck paramCheckAnnotation = parameter.getAnnotation(ParamCheck.class); if (paramCheckAnnotation != null) { String expression = paramCheckAnnotation.value(); // 根据expression对number进行校验 // ... } } ``` 最后,我们可以在调用checkNumber方法时传入一个不满足校验规则的参数,比如-10,当方法内部进行参数校验时,可以捕获到校验失败的情况,并进行相应处理。 ```java checkNumber(-10); // 参数校验失败,抛出异常或者进行其他处理 ``` 通过自定义注解实现参数校验可以方便地对代码进行统一的校验规则管理,提高代码的可维护性和可读性。同时,由于注解是在运行时通过反射获取,可以对代码进行动态改变和扩展,使得我们可以更加灵活地进行参数校验

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值