在实现导入功能时,一般要考虑下面几个点
表头正确性校验 ,如果表头不正确直接返回异常
表中值校验
导入的Excel表中是否有唯一字段出现值相同的情况
每条数据的正确性校验,包括数据类型是否正确、值范围是否正确、字符串长度是否正确
如果一些字段关联着数据库,要求这些字段的值要在数据库中存在。则要查询数据库来做校验
值校验后的方案
出现值错误后是直接抛出异常?还是遍历完所有数据,把错误的数据进行处理,正确的数据进行保存
错误数据处理方案
把所有的错误数据用字符串保存并返回
把错误数据用Excel表进行导出、可以而外增加一个字段来保存每条数据的错误信息
正确数据处理
一些字段在数据库中是不能为空的,但是导入的时候可能不需要添加,例如在合同导入时、会填写供应商信息,这时候在保存到数据库时就要查询这个供应商是否存在,然后查询出供应商的信息并把供应商id也保存到对应的数据中
导入依赖
1 2 3 4 5 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>${easyexcel.version}</version> </dependency>
EasyExcel将读取Excel的生命周期抽象为几个阶段,这几个阶段都包含在ReadListener接口中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public interface ReadListener <T> extends Listener { void onException (Exception exception, AnalysisContext context) throws Exception; void invokeHead (Map<Integer, CellData> headMap, AnalysisContext context) ; void invoke (T data, AnalysisContext context) ; void extra (CellExtra extra, AnalysisContext context) ; void doAfterAllAnalysed (AnalysisContext context) ; boolean hasNext (AnalysisContext context) ; }
SpringBoot引入validation依赖
1 2 3 4 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
可以统一获取所有的数据的错误信息,然后再统一处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public void text (@Validated @RequestBody List<Contract> entitys) { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); for (Contract contract : entitys) { Set<ConstraintViolation<Contract>> violations = validator.validate(contract); if (!violations.isEmpty()) { for (ConstraintViolation<Contract> violation : violations) { String fieldName = violation.getPropertyPath().toString(); String errorMessage = violation.getMessage(); System.out.println("错误信息:" + fieldName + "--" + errorMessage); } } else { System.out.println("这条数据没问题:" + contract); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Data public class Contract { @Size(max = 100, message = "-合同编号的长度不能大于100-") @ExcelProperty("合同编号") private String contNumber; @NotNull(message = "-合同名称不能为空-") @Size(max = 512, message = "-合同名称的长度不能大于512-") @ExcelProperty("合同名称(必填)") private String name; @NotNull(message = "合同金额不能为空") @Digits(integer=8, fraction=2, message="合同金额精度不能超过8位,小数点后最多2位") @DecimalMin(value="0.00", message="合同金额不能为负数") @DecimalMax(value="9999999999.99", message="合同金额过大") @ExcelProperty("合同金额(元)(必填)") private BigDecimal conyAmount; }