文件导入之Validation校验List对象数组

背景:

  • 我们的接口是一个List对象,对象里面的数据基本都有一些基础数据校验的注解,我们怎么样才能校验这些基础规则呢?

  • 我们在导入excel文件进行数据录入的时候,数据录入也有基础的校验规则,这个时候我们又该如何少写代码让Validation框架来帮我们完成这些基础校验呢?

带着这个疑问,喊一句:翠花,上酸菜。

正文

首先定义我们的Validation的基础类,基础类只有一个字段:errMsg,用于我们校验不通过时候存储我们的提示信息:

java 复制代码
@Data
public class ValidationBaseDTO {
    private String errMsg;
}

然后定义我们的测试对象类,搞一个简单的,这个DTO集成我们的校验基础类

java 复制代码
@Data
public class ValidationTestDTO extends ValidationBaseDTO {

    @NotEmpty(message = "用户名不允许为空!")
    private String userName;

    @NotEmpty(message = "用户code不允许为空")
    private String userCode;

    private int age;

}

然后编写咱们的校验工具类:

java 复制代码
public class ValidationUtils{
    public static <E, T extends ValidationBaseDTO> List<T> validate(Validator validator, E e) {
        return validate(validator, e, Default.class);
    }

    public static <E, T extends ValidationBaseDTO> List<T> validate(Validator validator, E e, Class<?> groupClass) {
        Set<ConstraintViolation<E>> set = validator.validate(e, groupClass);
        if (CollectionUtils.isEmpty(set)) {
            return null;
        }
        Map<String, List<ConstraintViolation<E>>> resultGroup = set.stream().collect(Collectors.groupingBy(item -> item.getPropertyPath().toString().substring(0, item.getPropertyPath().toString().indexOf("."))));

        return resultGroup.entrySet().stream().map(item -> {
            T targetObject = (T)item.getValue().get(0).getLeafBean();
            String errMsg = String.join("|", item.getValue().stream().map(ConstraintViolation<E>::getMessage).collect(Collectors.toList()));
            targetObject.setErrMsg(errMsg);
            return targetObject;
        }).collect(Collectors.toList());
    }

}

校验工具类有了,那还得搞一个测试用的Controller

复制代码
java 复制代码
@Slf4j
@RestController
@RequestMapping(value = "validation")
@AllArgsConstructor
public class ValidationTestController {

    private final Validator validator;

    @RequestMapping(value = "validationTest")
    public CommonResult<List<ValidationTestDTO>> validationTest() {
        // 例如我们通过Excel导入的数据有两条,属性全为空
        ValidationTestDTO validationTestDTO1 = new ValidationTestDTO();
        ValidationTestDTO validationTestDTO2 = new ValidationTestDTO();
        List<ValidationTestDTO> validationTestDTOList = new ArrayList<>();
        validationTestDTOList.add(validationTestDTO1);
        validationTestDTOList.add(validationTestDTO2);

        // 校验结果如果为空,则说明全部通过,如果不为空,则说明有的校验没有通过
        List<ValidationTestDTO> resultList = ValidationUtils.validate(validator, new ValidatedList<>(validationTestDTOList));
        return ResultUtil.success(resultList);
    }
}

这里不得不提的就是,Validator 在Spring框架里面是有被实例化的,且由Sping框架管理,我们直接注入就可以了

差点忘了,如果需要校验List,我们还需要自定义一个ValidationList类,如下:

java 复制代码
public class ValidatedList<E> implements List<E>, Serializable {

    public ValidatedList(List<E> eList){
        this.list = eList;
    }
    @Valid
    private List<E> list = new LinkedList<>();

    @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);
    }
}

如果这个类不定义,直接传入我们请求参数的List,那是无效的;

启动,看效果:

添加图片注释,不超过 140 字(可选)

相关推荐
戎梓漩25 分钟前
windows下安装curl,并集成到visual studio
ide·windows·visual studio
Smartdaili China1 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
蓝田~2 小时前
观察者模式和订阅模式
windows·观察者模式
努力进修5 小时前
“探索Java List的无限可能:从基础到高级应用“
java·开发语言·list
梓仁沐白9 小时前
ubuntu+windows双系统切换后蓝牙设备无法连接
windows·ubuntu
‘’林花谢了春红‘’12 小时前
C++ list (链表)容器
c++·链表·list
九鼎科技-Leo13 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
阿龟在奔跑15 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
Yang.9915 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
我不瘦但很逗15 小时前
Windows下使用DBeaver连接云数据库(MySQL)
数据库·windows