在使用EasyExcel进行数据导入时,数据校验是确保数据质量和业务逻辑正确的重要步骤。本文将详细介绍如何在EasyExcel中设定数据校验规则,并通过代码示例和流程解析展示其实现过程。
EasyExcel 是阿里巴巴开源的一个基于 Java 的 Excel 处理工具,旨在简化 Excel 文件的读写操作。它支持大文件的高效读取,同时提供了灵活的数据校验机制。
在实际项目中,用户上传的 Excel 文件可能包含各种错误数据,如格式不正确、超出范围的数值或非法字符等。如果不加以校验,这些错误数据可能会导致程序崩溃或产生错误结果。因此,在导入数据前进行严格的校验是非常必要的。
首先需要定义一个与 Excel 表格结构对应的实体类,并为每个字段添加校验注解。常见的校验注解包括 @NotNull
, @Min
, @Max
, @Pattern
等。
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ContentLoopMerge;
import javax.validation.constraints.*;
public class User {
@ExcelProperty("用户名")
@NotBlank(message = "用户名不能为空")
private String username;
@ExcelProperty("年龄")
@Min(value = 18, message = "年龄不能小于18岁")
@Max(value = 60, message = "年龄不能大于60岁")
private Integer age;
@ExcelProperty("邮箱")
@Email(message = "邮箱格式不正确")
private String email;
@ExcelProperty("注册日期")
@DateTimeFormat("yyyy-MM-dd")
private Date registerDate;
// Getters and Setters
}
如果内置的校验注解无法满足需求,可以通过实现自定义校验器来扩展功能。例如,检查某个字段是否唯一。
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import java.util.HashSet;
import java.util.Set;
public class UniqueUsernameVerifier implements CellWriteHandler {
private final Set<String> usernames = new HashSet<>();
@Override
public void afterCellDispose(WriteCellData<?> cellData, Sheet sheet, Cell cell) {
if (cell.getColumnIndex() == 0) { // 假设用户名在第一列
String username = cell.getStringCellValue();
if (!usernames.add(username)) {
throw new RuntimeException("用户名重复: " + username);
}
}
}
}
通过实现 AnalysisEventListener
接口,可以捕获每行数据并执行校验逻辑。
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class UserDataListener extends AnalysisEventListener<User> {
private List<User> failedRecords = new ArrayList<>();
@Override
public void invoke(User user, AnalysisContext context) {
try {
validate(user);
} catch (Exception e) {
failedRecords.add(user);
}
}
private void validate(User user) throws Exception {
if (user.getAge() < 18 || user.getAge() > 60) {
throw new IllegalArgumentException("年龄不在有效范围内");
}
if (!user.getEmail().matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")) {
throw new IllegalArgumentException("邮箱格式不正确");
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (!failedRecords.isEmpty()) {
System.out.println("以下记录未通过校验:");
for (User user : failedRecords) {
System.out.println(user.toString());
}
}
}
}
import com.alibaba.excel.EasyExcel;
public class ExcelImportDemo {
public static void main(String[] args) {
String fileName = "users.xlsx";
EasyExcel.read(fileName, User.class, new UserDataListener()).sheet().doRead();
}
}
graph TD; A[开始] --> B[读取Excel文件]; B --> C{是否有下一行}; C --是--> D[解析当前行数据]; D --> E[应用校验规则]; E --> F{是否通过校验}; F --否--> G[记录失败信息]; F --是--> H[继续处理下一行]; H --> C; C --否--> I[结束并输出校验结果];