EasyExcel结合validation实现导入数据的校验

在实现导入功能时,一般要考虑下面几个点

  • 表头正确性校验,如果表头不正确直接返回异常
  • 表中值校验
    • 导入的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 {
/**
* 当任何一个侦听器执行错误报告时,所有侦听器都将接收此方法。 如果在此处引发异常,则整个读取将终止。
* 这里是处理读取excel异常的
*
* @param exception
* @param context
* @throws Exception
*/
void onException(Exception exception, AnalysisContext context) throws Exception;

/**
* 读取每行excel表头时会执行此方法
*
* @param headMap
* @param context
*/
void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context);

/**
* 读取每行数据的时候回执行此方法
*
* @param data
* one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
* analysis context
*/
void invoke(T data, AnalysisContext context);

/**
* 如果有额外的单元格信息返回就用此方法处理
*
* @param extra
* extra information
* @param context
* analysis context
*/
void extra(CellExtra extra, AnalysisContext context);

/**
* 在整个excel sheet解析完毕后执行的逻辑。
*
* @param context
*/
void doAfterAllAnalysed(AnalysisContext context);

/**
* 用来控制是否读取下一行的策略
*
* @param context
* @return
*/
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;
}


EasyExcel结合validation实现导入数据的校验
https://lzhengjy.github.io/2024/09/01/EasyExcel结合validation实现导入数据的校验/
作者
Zheng
发布于
2024年9月1日
许可协议