文件导入之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 字(可选)

相关推荐
Byron Loong31 分钟前
【逆向】Windows 三大注入:远程线程 、APC 、 钩子注入
windows
凤舞飘伶41 分钟前
windows安装docker-desk
windows·docker·容器
绿豆人1 小时前
Cache缓存项目学习4
windows·学习·缓存
LuDvei2 小时前
Windows x86 架构下 Ubuntu 虚拟机内打包 Qt 文件指南
windows·qt·ubuntu
勤劳的进取家2 小时前
服务器文件交互方式
运维·服务器·microsoft
飞Link3 小时前
巨头混战医疗 AI!OpenAI、Anthropic 与微软的 Healthcare 助理技术架构对比
人工智能·microsoft·架构
庞轩px4 小时前
第一篇:Redis数据结构底层——String、List、Hash、Set、ZSet各自用什么实现的?
数据结构·redis·list·set·hash·string·zset
数据法师4 小时前
Wise Force Deleter:专门解决Windows文件“无法删除”问题的免费工具
windows
葡萄城技术团队5 小时前
AI没有缓解IT与业务的矛盾,有时反而激化了它
人工智能·microsoft
学习中.........5 小时前
Windows 上用 cc-connect 接入 Telegram + Codex:从零跑通与避坑指南
windows