使用EasyExcel解析导入文件
- 自定义Excel工具类,提供导入Excel文件的功能。
- 自定义Excel读取监听器Datalistener,用于数据处理。
- 实现了ReadListener接口,用于监听Excel的读取过程。
- 过滤导入的Excel文件中存在的非中文、英文和数字字符。
/**
* 导入文件方法。
*
* @param cla 数据模型类,用于解析Excel数据。
* @param file 待导入的文件,使用MultipartFile封装。
* @param allowedExtensions 允许的文件扩展名,多个扩展名使用英文逗号分隔。
* @param maxRows 导入数据的最大行数。
* @return 解析后的数据列表。
* @throws IllegalArgumentException 如果允许的文件扩展名为空,抛出此异常。
* @throws FileFormatIncorrectException 如果上传文件格式不正确,抛出此异常。
* @throws DataIsEmptyException 如果导入信息为空,抛出此异常。
* @throws ImportDataLimitExceededException 如果数据超过导入条数限制,抛出此异常。
* @throws FileReadException 如果文件读取失败,抛出此异常。
*/
public static <T> List<T> importFile(Class<T> cla, MultipartFile file, String allowedExtensions, int maxRows) {
// 检查允许的文件扩展名是否为空
if (allowedExtensions == null || allowedExtensions.isEmpty()) {
throw new IllegalArgumentException("允许的文件扩展名不能为空");
}
// 处理允许的文件扩展名,避免正则表达式错误
String escapedAllowedExtensions = allowedExtensions.replaceAll("[\\\\^$.|?*+()\\[\\]{}]", "\\\\$0");
String originalFilename = file.getOriginalFilename();
// 检查文件类型是否符合要求
if (!originalFilename.matches(".*\\." + escapedAllowedExtensions + "$")) {
throw new FileFormatIncorrectException("上传文件格式不正确,请下载模板文件上传");
}
try (InputStream inputstream = file.getInputStream()) {
List<T> list = EasyExcelFactory.read(inputstream, new Datalistener()).sheet(0)
.head(cla).headRowNumber(1).doReadSync();
// 检查导入数据是否为空
if (list.isEmpty()) {
throw new DataIsEmptyException("导入信息为空");
}
// 检查导入数据是否超过最大行数
if (list.size() > maxRows) {
throw new ImportDataLimitExceededException("超过导入条数限制,请确认!");
}
return list;
} catch (IOException e) {
// 记录文件读取失败的日志
logError("文件读取失败", e);
throw new FileReadException("文件读取失败:" + e.getMessage(), e);
} catch (Exception e) {
// 记录未预期错误的日志
logError("导入文件时发生意外错误", e);
throw new RuntimeException("导入文件时发生意外错误", e);
}
}
自定义异常抛出方法—>可以替换为需要的业务异常
// 错误日志记录方法
private static void logError(String message, Exception e) {
// 实现日志记录,这里仅作演示
System.out.println(message + ": " + e.getMessage());
}
// 定义相关异常类
static class FileFormatIncorrectException extends RuntimeException {
public FileFormatIncorrectException(String message) {
super(message);
}
}
static class DataIsEmptyException extends RuntimeException {
public DataIsEmptyException(String message) {
super(message);
}
}
static class ImportDataLimitExceededException extends RuntimeException {
public ImportDataLimitExceededException(String message) {
super(message);
}
}
static class FileReadException extends RuntimeException {
public FileReadException(String message, Throwable cause) {
super(message, cause);
}
}
自定义Excel读取监听器
public class Datalistener implements ReadListener<Object> {
// 定义一个正则表达式,用于过滤字符串中的非中文、英文和数字字符
public static final String REGEX = "^[\\u4e00-\\u9fa5_a-zA-Z0-9]+$";
/**
* 当读取到一行数据时调用此方法。
* @param object 读取到的数据对象
* @param analysisContext 分析上下文
*/
@Override
public void invoke(Object object, AnalysisContext analysisContext) {
Class<?> clazz = object.getClass(); // 获取当前对象的类
Field[] fields = clazz.getDeclaredFields(); // 获取所有声明的字段
for (Field field : fields) {
// 判断字段类型是否为String
if (field.getType().equals(String.class)) {
ReflectionUtils.makeAccessible(field); // 使私有字段可访问
try {
Object obj = field.get(object); // 获取字段值
if (obj != null) {
// 如果字段值不为空,则过滤字符串中的非中文、英文和数字字符
String value = String.valueOf(obj).replaceAll(REGEX, "");
field.set(object, value); // 设置过滤后的值回对象
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
analysisContext.readRowHolder().setCurrentRowAnalysisResult(object);
}
/**
* 当所有数据读取完成时调用此方法。
* @param analysisContext 分析上下文
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}