Excel导入且进行数据校验

news2024/12/25 13:28:17

目录

​​​​​​一、产品需求

二、解决方法

方案一:大量if-else判断校验

方案二:请求体加入注解进行校验

三、测试结果


 

一、产品需求

1.下载指定的excel数据模板

2.excel模板写入数据并导入

3.导入的时候根据校验规则进行筛选,导入成功的返回成功列表,数据存在问题的返回失败列表,失败列表支持数据编辑修正

看到需求的第一眼,可能就觉得第三点有点难度,我们知道,传统的数据校验可以通过在传输对象dto上面加注解实现。

//第一种
public Result test1(@RequestBody @Validated TestDTO dto) {...}

//第二种
public Result test2(@RequestBody @Valid TestDTO dto{...}

//第三种
public Result test3(@RequestBody @Validated(value = {SaveGroup.class}) TestDTO dto) {...}

TestDTO里面会有一些类似 @NotNull@NotBlank@Size等校验注解,这里就不列了。

然后在全局异常拦截那里进行统一封装,使其返回的数据结构尽量保持统一,所以一般还得有一个RestExceptionHandler类。

@ControllerAdvice
public class RestExceptionHandler {

    /**
     * 处理参数验证失败异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    private Response<?> methodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.warn("MethodArgumentNotValidException", e);
        FieldError fieldError = e.getBindingResult().getFieldError();
        return ResponseUtils.create(CommonCodeEnum.VALIDATE_ERROR.getCode(), CommonCodeEnum.VALIDATE_ERROR.getMessage(), fieldError.getDefaultMessage());
    }
}

讲到常见的数据校验,那么我们画风一转,再回来看需求,可见以上是不满足需求的,首先,我们的入参是一个文件流(指定的Excel模板文件),我们得先解析文件再进行数据校验,合法的放一个集合,不合法的放另一个集合;再者,即使入参是一个数组,这种校验一旦不满足立马进异常处理了,无法返回给前端正确的数据结构,所以今天就分享解决这类需求的解决方案。 

二、解决方法

基础数据

UserExcelVO

import lombok.Data;

import java.util.List;

/**
 *
 */
@Data
public class UserExcelVO {

    /**
     * 成功列表
     */
    private List<UserExcel> success;

    /**
     * 失败列表
     */
    private List<UserExcel> fail;
}

UserExcel

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.io.Serializable;

/**
 *
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserExcel implements Serializable {

    @NotBlank(message = "手机号不能为空")
    @Size(max = 4)
    @ExcelProperty(value = "用户名", index = 0)
    private String name;

    @ExcelProperty(value = "年龄", index = 1)
    private Integer age;

    @Pattern(regexp = "^[1][3,4,5,7,8][0-9]{9}$$", message = "手机号不合法")
    @NotBlank(message = "手机号不能为空")
    @ExcelProperty(value = "手机号", index = 2)
    private String mobile;

    @ExcelProperty(value = "性别", index = 3)
    private String sex;

}

excel模板数据

 

方案一:大量if-else判断校验

import com.alibaba.excel.EasyExcel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@RestController
@RequestMapping("/excel")
public class ExcelController {

    @PostMapping("/importExcel1")
    public UserExcelVO importExcel(@RequestParam("file") MultipartFile file) {
        List<UserExcel> list;
        List<UserExcel> fail = new ArrayList<>();
        UserExcelVO userExcelVO = new UserExcelVO();
        String mobileReg = "^[1][3,4,5,7,8][0-9]{9}$";
        try {
            list = EasyExcel.read(file.getInputStream(), UserExcel.class, new ModelExcelListener()).sheet().doReadSync();

            list.forEach(data -> {
                // 处理姓名的校验
                if (StringUtils.isEmpty(data.getName()) || data.getName().length() > 4) {
                    fail.add(data);
                    return;
                }
                // 处理手机号的校验
                if (StringUtils.isEmpty(data.getMobile()) || !data.getMobile().matches(mobileReg)) {
                    fail.add(data);
                    return;
                }
                // 以下根据字段多少可能有n个if...

            });
            userExcelVO.setFail(fail);
            list.removeAll(fail);
            userExcelVO.setSuccess(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userExcelVO;
    }

}

方案二:请求体加入注解进行校验

实际的业务场景,一个excel里面假如是订单数据,最少是几十个字段起步的,难道要写几十个if else吗?方案一明显是不合理的,因此使用注解的方式帮我们解决。

ValidationUtils

import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

/**
 *
 */
public class ValidationUtils {

    public static Validator getValidator() {
        return validator;
    }

    static Validator validator;

    static {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        validator = validatorFactory.getValidator();
    }

}

ModelExcelListener

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@Slf4j
public class ModelExcelListener extends AnalysisEventListener<UserExcel> {

    private List<UserExcel> datas = new ArrayList<>();

    /**
     * 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
     */
    @Override
    public void invoke(UserExcel data, AnalysisContext context) {
        //数据存储到list,供批量处理,或后续自己业务逻辑处理。
        log.info("读取到数据{}",data);
        datas.add(data);
        //根据业务自行处理,可以写入数据库等等

    }

    //所有的数据解析完了调用
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成");
    }

}

 请求

import com.alibaba.excel.EasyExcel;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.ConstraintViolation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 *
 */
@RestController
@RequestMapping("/excel")
public class ExcelController {

    @PostMapping("/importExcel2")
    public UserExcelVO importExcelV2(@RequestParam("file") MultipartFile file) {
        List<UserExcel> list;
        List<UserExcel> fail = new ArrayList<>();
        UserExcelVO userExcelVO = new UserExcelVO();
        try {
            list = EasyExcel.read(file.getInputStream(), UserExcel.class, new ModelExcelListener()).sheet().doReadSync();
            list.forEach(data -> {
                Set<ConstraintViolation<UserExcel>> violations = ValidationUtils.getValidator().validate(data);
                if (violations.size() > 0) {
                    fail.add(data);
                }
            });
            userExcelVO.setFail(fail);
            list.removeAll(fail);
            userExcelVO.setSuccess(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userExcelVO;
    }

}

三、测试结果

方案一的结果:

{
    "success": [
        {
            "name": "张2",
            "age": 19,
            "mobile": "13056781235",
            "sex": "女"
        },
        {
            "name": "张3",
            "age": 20,
            "mobile": "13056781236",
            "sex": "男"
        },
        {
            "name": "张4",
            "age": 21,
            "mobile": "13056781237",
            "sex": "女"
        },
        {
            "name": "张5",
            "age": 22,
            "mobile": "13056781238",
            "sex": "男"
        },
        {
            "name": "张6",
            "age": 23,
            "mobile": "13056781239",
            "sex": "男"
        },
        {
            "name": "张7",
            "age": 24,
            "mobile": "13056781240",
            "sex": "男"
        },
        {
            "name": "张8",
            "age": 25,
            "mobile": "13056781241",
            "sex": "男"
        },
        {
            "name": "张9",
            "age": 26,
            "mobile": "13056781242",
            "sex": "男"
        }
    ],
    "fail": [
        {
            "name": "张1",
            "age": 18,
            "mobile": "3056781234",
            "sex": "男"
        },
        {
            "name": "张10",
            "age": 27,
            "mobile": "130567812436",
            "sex": "男"
        }
    ]
}

方案二的结果:

{
    "success": [
        {
            "name": "张2",
            "age": 19,
            "mobile": "13056781235",
            "sex": "女"
        },
        {
            "name": "张3",
            "age": 20,
            "mobile": "13056781236",
            "sex": "男"
        },
        {
            "name": "张4",
            "age": 21,
            "mobile": "13056781237",
            "sex": "女"
        },
        {
            "name": "张5",
            "age": 22,
            "mobile": "13056781238",
            "sex": "男"
        },
        {
            "name": "张6",
            "age": 23,
            "mobile": "13056781239",
            "sex": "男"
        },
        {
            "name": "张7",
            "age": 24,
            "mobile": "13056781240",
            "sex": "男"
        },
        {
            "name": "张8",
            "age": 25,
            "mobile": "13056781241",
            "sex": "男"
        },
        {
            "name": "张9",
            "age": 26,
            "mobile": "13056781242",
            "sex": "男"
        }
    ],
    "fail": [
        {
            "name": "张1",
            "age": 18,
            "mobile": "3056781234",
            "sex": "男"
        },
        {
            "name": "张10",
            "age": 27,
            "mobile": "130567812436",
            "sex": "男"
        }
    ]
}

发现两种方案的测试结果虽然是一样的,但是很明显,方案二更优秀。我们后续写代码的时候,除了做功能,也要考虑代码的扩展性,不然产品说加个功能,我们又得吭哧吭哧写代码了。

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1100814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

防坠安全带上亚马逊合规认证合规标准是什么?如何办理?

防坠安全带 防坠安全带是一种防护装备&#xff0c;适合工人在高空作业时或在可能发生跌落的无防护边缘行走时穿着。防坠安全带设计用于包裹身体躯干&#xff0c;并将坠落力至少分布到大腿上部、骨盆、胸部和肩部。防坠安全带是固定物体与非固定物体之间的连接物&#xff0c;通…

WAILS安装

支持的平台 Windows 10/11 AMD64/ARM64 MacOS 10.13 AMD64 MacOS 11.0 ARM64 Linux AMD64/ARM64 依赖 Wails 有许多安装前需要的常见依赖项&#xff1a; Go 1.18 NPM (Node 15) Go 从 Go 下载页面 下载 Go。 确保您遵守官方的 Go 安装说明。 您还需要确保您的 PATH 环境变…

Unity中Shader的深度测试ZTest

文章目录 前言一、深度测试是干什么的二、图示讲解深度测试的作用三、深度值的测试操作1、设置为测试不通过&#xff0c;看看效果2、使用开关控制是否开启深度测试 前言 Unity中Shader的深度测试ZTest 一、深度测试是干什么的 通俗的讲&#xff0c;深度测试就是颜色在写入颜色…

JAVA基础(JAVA SE)学习笔记(一)JAVA学习路线、行业了解、开发环境JDK17安装配置 和 JDK8同时配置

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 2. 一步一个脚印&#xff0c;踏踏实实再学一遍&#xff01; 这个世界上有的人输在不能开始&#xff0c;有的人…

计算机视觉开源代码汇总

1.【基础网络架构】Regularization of polynomial networks for image recognition 论文地址&#xff1a;https://arxiv.org/pdf/2303.13896.pdf 开源代码:https://github.com/grigorisg9gr/regularized_polynomials 2.【目标检测&#xff1a;域自适应】2PCNet: Two-Phase Cons…

出行OTA渠道规则

1、目前出行行业的OTA主要有以下9个平台 携程&#xff08;携程包车&#xff09;、飞猪、航旅、曹操、同程、12306、高德、美团、南航 2、渠道对接 1、商务沟通&#xff1a;找到渠道对接负责人&#xff0c;洽谈对接事宜 2、资质审核&#xff1a;根据对接沟通中的平台线上所需…

QT基础入门——项目案例(七)

前言&#xff1a; 前面我们已经把基础的QT知识学习了一遍&#xff0c;已经足够运用这些知识做一个简单的小项目了&#xff0c;那么现在就让我们将所学的知识运用到现实操作中&#xff0c;来做一个简单的翻硬币小项目练练手吧 目录 一、项目简介&#xff1a; 二、项目的基本…

PyPy+Cython对Python进行加速,以及乱码问题

在之前测试了使用Cython对代码进行优化加速 https://blog.csdn.net/qq_43199509/article/details/133860665 PyPy具体是啥可以看之前的知乎介绍&#xff0c;个人理解就是Python的另一种解释器 https://www.zhihu.com/question/266096929/answer/2383570933 PyPy下载 https://…

知名低代码公司有哪些?最新国内十大低代码平台排名

什么是低代码和低代码平台 低代码&#xff08;Low-Code&#xff09;是一种软件开发方法&#xff0c;它使得开发人员能够通过图形界面、拖放组件和模型驱动的逻辑&#xff0c;快速地构建和部署应用程序&#xff0c;而无需编写大量的代码。 而低代码开发平台&#xff08;LCDP&am…

Sync Folders Pro for Mac文件夹数据同步工具

Sync Folders Pro for Mac 是一款功能强大的文件夹同步工具&#xff0c;旨在帮助用户在 Mac 计算机和移动设备之间创建双向同步。这款软件支持各种文件系统和设备&#xff0c;如 iPhone&#xff0c;iPad&#xff0c;iPod&#xff0c;Android 等。通过这款软件&#xff0c;用户可…

众和策略:几点开盘和收盘股票?

股票开盘和收盘时间是投资者有必要知道的要害信息&#xff0c;因为它们挑选了股票生意的初步和结束时间。在此文章中&#xff0c;咱们将从多个视点分析股票开盘和收盘时间&#xff0c;包括全球商场开盘时间、技术分析对开盘前后价格不坚决的影响、以及日内生意者如安在开盘和收…

【社区小程序制作】便捷社区服务的新选择

社区小程序的出现为居民提供了便捷的社区服务&#xff0c;促进了社区内的信息共享和互动。下面将介绍社区小程序的优点和制作流程。 优点 便捷的社区服务&#xff1a;社区小程序为居民提供了便捷的社区服务。居民可以通过小程序查询社区通知、报修维修等&#xff0c;高效且节省…

字符与数字的相互转换

一、字符转数字 char类型字符转换为数字&#xff0c;其实是转换为ASCII码值 有两种方式&#xff1a; 1.强制类型转换&#xff0c;结果为对应的ASCII码值 char v1 a;char v2 z;char v3 1;char v4 9;int num1 (int)v1;int num2 (int)v2;int num3 (int)v3;int num4 (int)v…

word字间距突然变大怎么办?

文章目录 原因&#xff1a;word字间距突然变大&#xff0c;是文字布局设置造成的。 解决方法如下&#xff1a; 1、首先在打开的文档中&#xff0c;可以看到如下图所示部分字间距变大。 2、这时鼠标选中字间距变大的区域、或者全选该部分文字。命令选项卡内一般选择文字靠左设置…

微信视频发出去后无法播放怎么办?解决办法来了

微信作为现今生活工作使用最频繁的软件之一&#xff0c;发送文档、播放视频、分享照片截图等是经常操作的&#xff0c;然而当我们向对方发送一个视频文件的时候&#xff0c;电脑端播放器播放正常&#xff0c;通过微信发出去之后结果无法播放了。其实微信无法播放视频有很多原因…

(三十四)大数据实战——scala运行环境安装配置及IDEA开发工具集成

前言 本节内容我们主要介绍一下scala运行环境的安装配置以及在idea开发工具中集成scala插件&#xff0c;便于scala项目的开发。 在开始scala安装配置之前&#xff0c;我们要先安装好jvm运行环境&#xff0c;scala运行于Java虚拟机&#xff08;JVM&#xff09;上&#xff0c;并…

JS中欺骗词法作用域的eval和with

1、词法作用域 简单地说&#xff0c;词法作用域就是定义在词法阶段的作用域。换句话说&#xff0c;词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的&#xff0c;因此当词法分析器处理代码时会保持作用域不变&#xff08;大部分情况下是这样的&#xff09;。 考虑…

上抖音热搜榜需要怎么做?

抖音热搜榜是根据用户的搜索行为和搜索量数据进行排名的榜单。具体排名规则如下&#xff1a; 1. 关键词匹配度&#xff1a;抖音搜索引擎会根据用户搜索的关键词与视频标题、标签、内容等进行匹配&#xff0c;匹配度越高&#xff0c;排名越靠前。 2. 视频质量&#xff1a;抖音…

6-k8s-控制器版本管理

文章目录 一、概念介绍二、配置介绍三、版本生成测试四、版本回滚测试 一、概念介绍 什么是控制器&#xff1a;在k8s中&#xff0c;控制器是一种用于控制和管理Pod的管理器&#xff0c;包括Deployment、ReplicaSet、StatefulSet等。 什么是控制器版本管理&#xff1a;是指对于…

django无法导入第三方库

引子 有的人可能会很困惑&#xff0c;为什么自己在pip中安装了某个包&#xff0c;但是在django中死活无法导入。 在cmd中能够导入。 启动django&#xff0c;总是无法导入。 本文将会用一分钟解决你的困惑。 正文 那么本文以上述的第三方库dj_db_conn_pool为例&#xff0c;…