項(xiàng)目要求
實(shí)際項(xiàng)目中存在諸多場(chǎng)景需要校驗(yàn)入?yún)?shù)據(jù)。繁雜的參數(shù)校驗(yàn)占據(jù)相當(dāng)部分的代碼量,且不友好。
為便于實(shí)際開發(fā)寫出此注解,切合實(shí)際的開發(fā)需求,多種場(chǎng)景的數(shù)據(jù)校驗(yàn),并拋出自定義的異常信息,便于控制層處理,簡(jiǎn)化代碼。
對(duì)比優(yōu)勢(shì)
1.繁雜的Hibernate校驗(yàn)注解,且不宜定制化開發(fā),不適合多場(chǎng)景數(shù)據(jù)校驗(yàn)。
2.自定義注解,配合多場(chǎng)景數(shù)據(jù)校驗(yàn),可定制化配置,可擴(kuò)展,高效,易懂的配置。
自定義注解
- 注解類
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 校驗(yàn)參數(shù)注解 可根據(jù)需要擴(kuò)展校驗(yàn)數(shù)據(jù)的選項(xiàng),比如值區(qū)間max,min,值域
* @author vinod
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Validation {
//校驗(yàn)的屬性的類型
ValidateType value() default ValidateType.TYPE_STRING;
//配置則根據(jù)當(dāng)前字段校驗(yàn) 默認(rèn)為空
String accordField() default "";
//根據(jù)accordField的值校驗(yàn)值 默認(rèn)為空
String accordValue() default "";
//正數(shù)校驗(yàn) 默認(rèn)不校驗(yàn)
boolean isPositive() default false;
}
- 數(shù)據(jù)類型枚舉
/**
* 校驗(yàn)枚舉
* @author vinod
*/
public enum ValidateType {
TYPE_STRING,
TYPE_INTEGER,
TYPE_CHAR,
TYPE_LONG,
TYPE_FLOAT,
TYPE_DOUBLE,
TYPE_BOOLEAN,
TYPE_DATE,
TYPE_LIST,
TYPE_MAP,
TYPE_SET,
TYPE_OBJECT
}
注解處理類
1.注解使用: bean中聲明屬性校驗(yàn)
public class UserInfo implements Serializable{
@Validate(ValidateType.TYPE_STRING)
private String username;
// 此處則可配置值域?yàn)?1,2),需擴(kuò)展注解
private Integer sex; // 1:男 2:女
// 配置當(dāng)前字段根據(jù)sex=2時(shí)才校驗(yàn)非空,
@Validate(value = ValidateType.TYPE_STRING,accordField = "sex",accordValue = "2")
private String size;
}
2.調(diào)用方法處理
// 1.1 校驗(yàn)必填字段
ValidationHandler.validateParams(req);
3.注解處理類源代碼
import com.vinod.test.util.exception.UserDefineException;
import com.vinod.test.util.annotation.Validation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 僅處理傳入object中的Validate注解
* @author vinod
*/
public class ValidationHandler {
private static Logger logger = LoggerFactory.getLogger(ValidationHandler.class);
// 方法重載
public static void validateParams(Object obj){
validateParams(obj,null,true);
}
public static void validateParams(Object obj,boolean accordFlag){
validateParams(obj,null,accordFlag);
}
/**
* 校驗(yàn)參數(shù)不為空
* @param obj 需要校驗(yàn)的對(duì)象
* @param excludeParams 需要排除校驗(yàn)的屬性名集合
* @param accordFlag 根據(jù)屬性依賴校驗(yàn)
*/
public static void validateParams(Object obj,Set<String> excludeParams,boolean accordFlag){
logger.info("xxxx日志記錄");
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
Object value = field.get(obj);
// 當(dāng)前屬性在需要排除校驗(yàn)的集合中時(shí),跳過當(dāng)前字段校驗(yàn)。
if(excludeParams!=null&&excludeParams.contains(field.getName())){
continue;
}
Validation annotation = (Validation)field.getAnnotation(Validation.class);
//System.out.println("=====----"+annotation+"---> "+field.getName());
//注解存在時(shí),則說明當(dāng)前字段需要校驗(yàn)
if(annotation!=null){
// 是否根據(jù)依據(jù)篩選為空屬性
if(accordFlag){
// 根據(jù)某字段判別是否為空
if(StringUtils.isNotEmpty(annotation.accordField())){
Field accordField = obj.getClass().getDeclaredField(annotation.accordField());
accordField.setAccessible(true);
Object accordValue = accordField.get(obj);
// 為空或不等于注解預(yù)設(shè)值則跳過當(dāng)前屬性的校驗(yàn)
if(accordValue==null||!accordValue.toString().equals(annotation.accordValue())){
continue;
}
}
}
// 屬性值不能為空
if(value==null){
throw new UserDefineException(field.getName());
}
checkTypeEnumValue(annotation,field,value,annotation.isPositive());
}
} catch (IllegalAccessException e) {
// e.printStackTrace();
logger.info("xxxx日志記錄");
//拋出自定義異常信息
throw new UserDefineException(field.getName());
} catch (NoSuchFieldException e) {
logger.info("xxxx日志記錄");
//拋出自定義異常信息
throw new UserDefineException(field.getName());
}
}
}
/**
* 校驗(yàn)注解配置的屬性值
* @param annotation
* @param field
* @param value
* @param isPositive
*/
private static void checkTypeEnumValue(Validation annotation, Field field, Object value,boolean isPositive){
// 暫值列舉幾種數(shù)據(jù)處理,剩余類型處理類似
switch (annotation.value()){
case TYPE_STRING:
if(StringUtils.isEmpty(value.toString())||"null".equals(value.toString().toLowerCase())){
throw new UserDefineException(field.getName());
}
break;
case TYPE_LONG:
if(0L==(Long)value){
throw new UserDefineException(field.getName());
}
if(isPositive&&(Long)value<0){
throw new UserDefineException(field.getName());
}
break;
}
}
}