想必大家在做参数验证的时候,都会遇到一个问题,就是如何验证枚举? 自定义annotation 自定义Validator

想必大家在SpringMVC项目做请求参数验证的时候,都会遇到一个问题,就是如何验证枚举?方法无外乎以下几种:
方法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);
}
}




posted @ 2017-04-25 11:12  TNZYM  阅读(4274)  评论(0编辑  收藏  举报