Custom annotations to implement excel import data parameter verification

A custom annotation

1. Meta-annotation

We need to add several meta-annotations to the custom annotations

@Target
@Retention
@Inherited
@Documented

1.1 Brief introduction

@Target
is used to declare where the current annotation can be used

value describe
ElementType.TYPE Applies to classes, interfaces (including annotation types), and enumerations
ElementType.FIELD Applies to properties (including constants in enumerations)
ElementType.METHOD Apply to method
ElementType.PARAMETER Formal parameters applied to methods
ElementType.CONSTRUCTOR applied to constructor
ElementType.LOCAL_VARIABLE applied to local variables
ElementType.ANNOTATION_TYPE Applies to annotation types
ElementType.PACKAGE applied to packages
ElementType.TYPE_PARAMETER applied to type variables
ElementType.TYPE_USE Applies to any statement that uses a type (such as types in declaration statements, generics, and cast statements)

@Retention
indicates the life cycle of the annotation

life cycle type describe
RetentionPolicy.SOURCE discarded at compile time and not included in the class file
RetentionPolicy.CLASS Discarded when JVM loads, included in class file, default value
RetentionPolicy.RUNTIME Loaded by the JVM, included in the class file, and can be obtained at runtime

@Inherited
indicates that the annotation of the @Inherited annotation is used, and subclasses of the marked class will also have this annotation.

@Document
indicates that the element marked by this annotation can be documented by Javadoc or similar tools.

Generally, it is enough to use the first three when declaring custom annotations.

2 Statement annotation

// {} 中可以声明多个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 "";
}

enum class

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;
	}

This annotation is declared

2. Verification Tools

Write verification tool class

/**
 * 导入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. Verification

3.1 Use custom annotations in excel templates

@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;

}

Guess you like

Origin blog.csdn.net/weixin_44931584/article/details/128956804