zoukankan      html  css  js  c++  java
  • 想必大家在做参数验证的时候,都会遇到一个问题,就是如何验证枚举? 自定义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);
    }
    }




  • 相关阅读:
    【数学】多项式取 ln
    【数学】多项式求逆
    【模拟 + 栈】AcWing 151. 表达式计算4
    Unity3D开发入门教程(一)——搭建开发环境
    Unity3D开发入门教程(三)——添加启动脚本
    Unity3D开发入门教程(二)—— Lua入门
    Unity3D开发入门教程(四)——用Lua实现组件
    哈希表
    邻接表
    并查集
  • 原文地址:https://www.cnblogs.com/tonyzeng/p/6761023.html
Copyright © 2011-2022 走看看