java自定义注解实现请求参数校验

java自定义注解实现请求参数校验

    • 创建自定义注解
    • 通过Java反射获取entity属性
    • AOP切面
    • 用法示例

创建自定义注解

// 加在属性字段上
@Traget(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNullField {
	
	// 最小值
	int min() default 0;
	
	// 最大值
	int max() default 0;

	// 最大长度
	int length() default 0;

	// 返回提示语
	String message() default "";
	
	// 正则表达式
	String pattern() default "";
}

// 加在需要校验参数的controller层方法上
@Traget(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidParams {

	boolean require() defaut true;
		
	Class clazz();
}

通过Java反射获取entity属性

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

public class ParamValidUtil<T> {
	public static <T> void checkParam(Class<T> clazz, Object obj) throws Illegalaccessexception  {
		Field field;
		NotNullField notNullField;
		Field[] fields = getAllFields(clazz);
		for(int i = 0; i < fields.length; i++) {
			field = fields[i];
			field.setAccessible(true);
			notNullField = field.getAnnotation(NotNullField.Class);
			if(null == notNullField ) {
				// 没有加注解的属性直接continue
				continue;
			}
			// 开始校验属性值
			checkValue(field.getType().getName(), field.getName(), notNullField);
		}
	}
	
	/**
	 * 获取所有属性(getSuperclass:获取父类属性)
	 * @param clazz
	 * @param 
	 * @return
	 */
	private static <T> Field[] getAllFields(Class<T> clazz) {
	    Class superClazz = clazz;
	    List<Field> fieldList = new ArrayList<>();
	    while (null != superClazz) {
	        fieldList.addAll(new ArrayList<>(Arrays.asList(superClazz.getDeclaredFields())));
	        superClazz = superClazz.getSuperclass();
	    }
	    Field[] fields = new Field[fieldList.size()];
	    fieldList.toArray(fields);
	    return fields;
	}
	
	/**
	 * 校验属性值
	 * 初稿
	 */
	private static void checkValue(String fieldType, String fieldName, Object value, NotNullField notNullField) {
		switch(fieldType) {
			case "java.lang.String":
				if(null == value || "".equals(value.toString())) {
					logger.error("{},field:{}", notNullField.message(), fieldName);
					// 返回自定义统一异常
					throw BusinessException.paramsError(notNullField.message());
				}
				break;
			case "java.lang.Integer":
			case "java.lang.Long":
			case "java.lang.Boolean":
			case "java.lang.Double":
			case "java.lang.Object":
				if (null == value) {
					logger.error("{},field:{}", notNullField.message(), fieldName);
					// 返回自定义统一异常
					throw BusinessException.paramsError(notNullField.message());
				}
				break;
			case "java.util.List":
				List<?> list = (List<?>) value;
				// 导入springframework包的CollectionUtils类
				if (CollectionUtils.isEmpty(list)) {
					logger.error("{},field:{}", notNullField.message(), fieldName);
					// 返回自定义统一异常
					throw BusinessException.paramsError(notNullField.message());
				}
				break;
			case "java.util.Map":
				Map<?, ?> map= (Map<?, ?> ) value;
				// 导入springframework包的CollectionUtils类
				if (CollectionUtils.isEmpty(map)) {
					logger.error("{},field:{}", notNullField.message(), fieldName);
					// 返回自定义统一异常
					throw BusinessException.paramsError(notNullField.message());
				}
				break;
			default:
				if (null == value) {
					logger.error("{},field:{}", notNullField.message(), fieldName);
					// 返回自定义统一异常
					throw BusinessException.paramsError(notNullField.message());
				}
				break;
		}
	}
}

AOP切面

创建AOP切面,在方法执行之前校验所有加了@NotNullField注解属性的值

@Aspect
@Componet
public class ValidParamsAspect {

	private Logger logger = Logger.getLogger(ValidParamsAspect.class);
	
	@Pointcut("@annotation(org.com.annotation.ValidParams)")
	public void asValidParamsAnnotation() {}

	@Before("asValidParamsAnnotation() && @annotation(validParams)")
	public void before(JoinPoint joinPoint, ValidParams validParams) {
		if (validParams.require()) {
			logger.info("开始校验请求参数");
			Object[] args = joinPoint.getArgs();
			if (args.length > 0) {
				try {
					ParamValidUtil.checkParam(validParams.clazz(), args[0]);
				} catch(Exception e) {
					logger.error("参数校验异常,参数类型不是entity类", e);
					throw BusinessException.runtimeError("参数校验异常,参数类型不是entity类", e);
				} 
			}
		} else {
			logger.info("当前请求不需要校验参数");
		}
	}
}

用法示例

在实体类的属性加上@NotNullField注解,代码:

public class TestEntity {
	
	private Integer id;
	@NotNullField(message = "名称不能为空")
	private String name;
	
	public Integer getId() {
		return id;
	}
	
	public void setId(Integer id) {
		this.id = id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setId(String name) {
		this.name = name;
	}
}

在controller层的方法加上@ValidParams注解

@RestController
@RequestMapping("test")
public class TestController {

	@PostMapping("myTest")
	@ValidParams(clazz = TestEntity.class)
	public void myTest(@RequestBody TestEntity testEntity) {
		System.out.println("hello world");
	}
}

你可能感兴趣的:(Java,Spring)