自定义注解实现参数校验

末尾有常用约束注解


一、自定义验证注解的好处

  • 验证逻辑和业务逻辑分离
  • 验证逻辑的复用

二、步骤

  • 自定义注解,指定验证器
  • 实现验证器

这里我们实现一个注解来验证参数是否为true或者false

首先,自定义注解 @BooleanCheck

@Target({ElementType.FIELD}) // 作用范围:字段
@Retention(RetentionPolicy.RUNTIME) // 最长生命周期:运行时保留
@Constraint(validatedBy = BooleanCheckValidator.class) // 表示这个注解是一个验证注解,并且指定了一个实现验证逻辑的验证器
@Documented
public @interface BooleanCheck {
    String message() default "err: strict must be true or false or not set"; // 参数,指明了验证失败后返回的消息

    // groups()和payload()也为@Constraint要求,可默认为空
    Class<?>[] groups() default {}; // 分组校验,不同的场景下有不同的验证逻辑,比如创建方法参数不能为空,更新方法参数可以为空

    Class<? extends Payload>[] payload() default {}; // 暂不清楚作用
}

第二步,创建验证器实现验证逻辑

/**
 * 验证器
 */
public class BooleanCheckValidator implements ConstraintValidator<BooleanCheck, String> {

    /**
     * 在参数验证开始前调用注解里的方法,从而获取到一些注解里的参数
     *
     * @param constraintAnnotation 自定义的注解
     */
    @Override
    public void initialize(BooleanCheck constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }

    /**
     * 验证器验证逻辑
     *
     * @param strict 需要验证的参数
     * @param constraintValidatorContext
     * @return 返回验证结果
     */
    @Override
    public boolean isValid(String strict, ConstraintValidatorContext constraintValidatorContext) {
        return strict.equals("true") || strict.equals("false");
    }
}

第三步,使用注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {

    private String name;

    @BooleanCheck
    private String strict;
}

第四步,开启验证,需要在验证的地方加上@Valid注解

@RestController
@RequestMapping("/hello")
public class TestController {

    /**
     * controller
     *
     * @param list     People集合对象
     * @param validRes 接收验证结果
     * @return
     */
    @PostMapping("/test")
    public String test(@Valid @RequestBody ValidList<People> list, BindingResult validRes) {
        if (validRes.hasErrors()) {
            // 返回自定义的验证失败信息
            return validRes.getAllErrors().get(0).getDefaultMessage();
        }
        return "OK!";
    }
}

第五步,@Valid只能验证单个实体类,对List集合不生效,需要我们自己定义个ValidList类实现List的方法,并使用自定义ValidList替换List的使用

/**
 * 校验List中字段属性
 *
 * @param <E>
 */
@Data
public class ValidList<E> implements List<E> {

    @Valid
    private List<E> list = new ArrayList<>();

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }

    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }

    @Override
    public Object[] toArray() {
        return list.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    @Override
    public boolean add(E e) {
        return list.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return list.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return list.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    @Override
    public void clear() {
        list.clear();
    }

    @Override
    public E get(int index) {
        return list.get(index);
    }

    @Override
    public E set(int index, E element) {
        return list.set(index, element);
    }

    @Override
    public void add(int index, E element) {
        list.add(index, element);
    }

    @Override
    public E remove(int index) {
        return list.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    @Override
    public ListIterator<E> listIterator() {
        return list.listIterator();
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return list.listIterator(index);
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }
}

第六步,Postman发送请求验证

数据正确
image

数据失败
image

posted @   Anti-kill  阅读(493)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示