方法1:直接用枚舉定義字段類型
方法2:用Integer類型定義字段類型,然后在代碼里面驗證(即:放棄使用
javax
.
validation.validator去統一驗證
)
缺點:
方法1的缺點:當枚舉的value值不是從0開始有序設置時,就會出現問題,因為雖然spring支持枚舉類型字段的解析,但其實它是根據枚舉的index,也就是索引來解析的。並且直接在請求字段上使用枚舉,這個不太規范,並且在Mapping到po或者vo的時候會存在轉值需要,即,得通過枚舉成員去拿value值設置給PO。
方法2的缺點:得寫多余的if...else來判斷,遠遠沒有validator的簡潔。代碼結構看上去就比較糟糕。
那么,難道就沒有解決辦法了嗎?當然不是,在程序員的世界,沒有不能解決的問題,只有等待解決的問題。解決方案如下:
目標:
即使用基礎類型作為字段類型,又可以使用枚舉來約束驗證字段。
原料:
1.枚舉一枚
2.自定義annotation一枚
3.自定義Validator一枚
步驟:
Step 1:自定義枚舉
Step 2:首先需要自定義一個annotation來標記你的驗證字段,因為Validator框架里面的基礎annotation已經不夠用。
Step 3:自定義一個Validator(繼承
ConstraintValidator
),並將Step2中annotation類型給到
ConstraintValidator
的泛型列表,相當於做了一個綁定。然后implement
ConstraintValidator
的兩個方法,在isValid方法里面用Step1的枚舉驗證參數。
Step 4:使用我們的老朋友Validator,盡情的驗證吧!
不多說,直接上干貨,JAVACODE:
/**
* 請求參數model
* Created by TonyZeng on 2017/3/25.
*/
public class AddQuestionRqVo {
/**
* 性別
*/
@CheckSex
private Integer sex;
}
/**
* 性別
* Created by TonyZeng on 2017/3/29.
*/
public enum SexType {
Free(0, "不限"),
Male(1, "男"),
Female(2, "女");
private int id;
private String chinese;
// 構造方法
SexType(int id, String chinese) {
this.id = id;
this.chinese = chinese;
}
public static SexType valueOf(int value) {
switch (value) {
case 0:
return SexType.Free;
case 1:
return SexType.Male;
case 2:
return SexType.Female;
default:
return null;
}
}
public static SexType textOf(String text) {
switch (text) {
case "不限":
return SexType.Free;
case "男":
return SexType.Male;
case "女":
return SexType.Female;
default:
return null;
}
}
//此處省略get&set方法
}
/**
* 用枚舉指定參數
* Created by TonyZeng on 2017/4/24.
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckSexValidator.class)
@Documented
public @interface CheckSex {
/**
* 用來定義默認得消息模版, 當這個約束條件被驗證失敗的時候,通過此屬性來輸出錯誤信息.
* @return
*/
String message() default "請提供正確的性別(ID)";
/**
* 用於指定這個約束條件屬於哪(些)個校驗組
* @return
*/
Class<?>[] groups() default {};
/**
* Bean Validation API 的使用者可以通過此屬性來給約束條件指定嚴重級別. 這個屬性並不被API自身所使用.
* @return
*/
Class<? extends Payload>[] payload() default {};
}
/**
* 自定義性別Validator
* Created by TonyZeng on 2017/4/25.
*/
public class CheckSexValidator implements ConstraintValidator<CheckSex, Integer> {
@Override
public void initialize(CheckSex constraintAnnotation) {
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return SexType.valueOf(value) != null;
}
}
/**
* Created by TonyZeng on 2016/9/6.
*/
public class ValidateUtil<T> {
private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
private static Validator validator = validatorFactory.getValidator();
/**
* 驗證請求參數
*
* @param model
* @return null 則說明驗證成功,如果非null 則說明驗證失敗
*/
public String validate(T model) {
model.getClass().getAnnotatedInterfaces();
Set<ConstraintViolation<T>> violations = validator.validate(model);
if (violations.size() > 0) {
String msg = "";
for (ConstraintViolation<T> violation : violations) {
msg += violation.getMessage() + "<br>";
}
return msg;
}
return null;
}
}
@Override
public BaseDto addQuestion(AddQuestionRqVo requestVo) {
String validateResult = new ValidateUtil<AddQuestionRqVo>().validate(requestVo);
if (validateResult != null) {
return new BaseDto(-1, validateResult);
}
}