В проекте обязательно будут некоторые функции импорта Excel. Существующая проблема: исключение преобразования типа при импорте. Если выдается только исключение ошибки, пользователь не может понять сообщение об ошибке. Лучше подсказать пользователю, какая строка и столбец. это аномалия в данных. Без дальнейших церемоний, давайте перейдем к коду.
Импортированная структураeasyExcel
: https://easyexcel.opensource.alibaba.com/
Код прослушивателя ExcelListener:
/**
* @author : Подметающий монах
* @date :2023/08/29 0029 13:35
* @version: V1.0
* @slogan: В моём поколении мир неспокойный, и как только я ввожу код, годы мчат меня
* @description: Универсальный EasyExcel слушатель
**/
@Slf4j
public final class ExcelListener<T> extends AnalysisEventListener<T> {
/**
* Настроено для временного хранения данных
* Значение можно получить через экземпляр
*/
private List<T> datas = new ArrayList<>();
/**
* Метод вызова() будет вызываться каждый раз при анализе строки.
* @param data объект данных после чтения
* @param context содержание
*/
@Override
public void invoke(T data, AnalysisContext context) {
datas.add(data);
}
/**
* Действия после прочтения
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("Чтение всех данных завершено");
}
/**
* аномальныйметод (Преобразование типа аномальный также будет выполнять этот метод) (Чтение аномальной строки также выполнит этот метод)
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
log.info("иметьаномальный"); // Если это преобразование определенной ячейки аномальное Можно получить конкретный номер строки
// Если вы хотите получить информацию заголовка Используется с ignoreHeadMap.
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
log.error("Нет.{}ХОРОШО,Нет.{}анализ столбцааномальный,данныедля:{}", excelDataConvertException.getRowIndex(),
excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
выдать новое RuntimeException("Нет."+excelDataConvertException.getRowIndex()+"ХОРОШО" +
"," + (excelDataConvertException.getColumnIndex() + 1) + «Ошибка чтения столбца»);
}
}
/**
* возвращатьсяданные * @return Возвращает прочитанную коллекцию данных.
**/
public List<T> getDatas() {
return datas;
}
}
Преимущество определения типа прослушивателя как общего заключается в том, что Независимо от того, какая таблица используется для функции импорта Требуется только этот прослушиватель, а конкретные бизнес-методы передаются Сервису. Уведомление:
RuntimeException
Исключения — это исключения времени выполнения Java, если в компании есть специально определенный класс исключений. Просто замените его
Код класса сущности
@Data
@TableName("sys_test")
public class SysTestEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* Имя
*/
@ExcelProperty("Имя")
private String name;
/**
* возраст
*/
@ExcelProperty("возраст")
private Integer age;
/**
* Номер телефона
*/
@ExcelProperty("Номер телефона")
private Integer phone;
/**
* зарплата
*/
@ExcelProperty("зарплата")
private BigDecimal salary;
/**
* День рождения
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty("День рождения")
private Date birthday;
}
код контроллера
@RestController
@RequestMapping("test/systest")
public class SysTestController {
@Autowired
private SysTestService sysTestService;
/**
* Импорт шаблона
* @param file
* @return
* @throws IOException
*/
@PostMapping("upload")
@ResponseBody
public Result upload(MultipartFile file) throws IOException {
//Используем дженерики для указания классов сущностей
ExcelListener<SysTestEntity> excelListener = new ExcelListener<>();
//читатьданные EasyExcel.read(file.getInputStream(),SysTestEntity.class,excelListener).headRowNumber(1).sheet(0).doRead();
//Получаем прочитанные данные
List<SysTestEntity> list = excelListener.getDatas();
//Используем метод пакетного добавления
sysTestService.saveBatch(list);
return ResultUtil.success("Импорт успешен");
}
}
Идеи реализации непустой проверки:
Пользовательские аннотации
/**
* @author : Подметающий монах
* @date :2023/08/29 0029 15:00
* @version: V1.0
* @slogan: В моём поколении мир неспокойный, и как только я ввожу код, годы мчат меня
* @description: ExcelValid ненулевая проверка аннотация
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelValid {
String message() default «Импорт имеет незаполненные поля»;
}
Пользовательский валидатор
/**
* @author : Подметающий монах
* @date :2023/08/29 0029 15:02
* @version: V1.0
* @slogan: В моём поколении мир неспокойный, и как только я ввожу код, годы мчат меня
* @description:
**/
public class ExcelImportValid {
/**
* Проверка поля импорта Excel
*
* @param object Проверенные JavaBeans Его атрибуты должны иметь Пользовательские аннотации
*/
public static void valid(Object object) {
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
//Установить доступный
field.setAccessible(true);
//значение атрибута
Object fieldValue = null;
try {
fieldValue = field.get(object);
} catch (IllegalAccessException e) {
throw new RuntimeException("Проверка параметров импорта не удалась");
}
//Содержит ли он необходимую аннотацию проверки
boolean isExcelValid = field.isAnnotationPresent(ExcelValid.class);
if (isExcelValid && Objects.isNull(fieldValue)) {
System.out.println("Ошибка импорта");
System.out.println(field.getAnnotation(ExcelValid.class).message());
throw new RuntimeException("NULL"+field.getAnnotation(ExcelValid.class).message());
}
}
}
}
Добавление аннотаций к классам сущностей
@Data
@TableName("sys_test")
public class SysTestEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
* Имя
*/
@ExcelProperty("Имя")
@ExcelValid(message = "Имяне могудлянулевой")
private String name;
/**
* возраст
*/
@ExcelProperty("возраст")
private Integer age;
/**
* Номер телефона
*/
@ExcelProperty("Номер телефона")
private Integer phone;
/**
* зарплата
*/
@ExcelProperty("зарплата")
private BigDecimal salary;
/**
* День рождения
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ExcelProperty("День рождения")
private Date birthday;
}
Код прослушивателя ExcelListener
/**
* @author : Подметающий монах
* @date :2023/08/29 0029 13:35
* @version: V1.0
* @slogan: В моём поколении мир неспокойный, и как только я ввожу код, годы мчат меня
* @description: Универсальный EasyExcel слушатель
**/
@Slf4j
public final class ExcelListener<T> extends AnalysisEventListener<T> {
/**
* Настроено для временного хранения данных
* Значение можно получить через экземпляр
*/
private List<T> datas = new ArrayList<>();
/**
* Метод вызова() будет вызываться каждый раз при анализе строки.
* @param data объект данных после чтения
* @param context содержание
*/
@Override
public void invoke(T data, AnalysisContext context) {
//данные сохраняются в списке для пакетной обработки или последующей обработки бизнес-логики.
try {
ExcelImportValid.valid(data);
datas.add(data);
} catch (Exception e) {
// Проверка не удалась, процесс аномальный
System.out.println("Проверка не удалась:" + e.getMessage());
// Другие меры обработки могут быть приняты по мере необходимости.
throw new ApiException(e.getMessage());
}
}
/**
* Действия после прочтения
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("Чтение всех данных завершено");
}
/**
* аномальныйметод (Преобразование типа аномальный также будет выполнять этот метод) (Чтение аномальной строки также выполнит этот метод)
*
* @param exception
* @param context
* @throws Exception
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
log.info("иметьаномальный"); // Если это преобразование определенной ячейки аномальное Можно получить конкретный номер строки
// Если вы хотите получить информацию заголовка Используется с ignoreHeadMap.
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
log.error("Нет.{}ХОРОШО,Нет.{}анализ столбцааномальный,данныедля:{}", excelDataConvertException.getRowIndex(),
excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
throw new ApiException("Нет."+excelDataConvertException.getRowIndex()+"ХОРОШО" +
"," + (excelDataConvertException.getColumnIndex() + 1) + «Ошибка чтения столбца»);
}
//Выдаем аномальную проверку на ненулевое значение
throw new ApiException(exception.getMessage());
}
/**
* возвращатьсяданные * @return Возвращает прочитанную коллекцию данных.
**/
public List<T> getDatas() {
return datas;
}
}
Есть яма: После того, как метод вызова генерирует исключение, система по-прежнему отображает успешный импорт и печатает сообщение об ошибке проверки. Внимательно прочитав официальную документацию, я обнаружил, что метод onException будет выполнен после создания исключения, и необходима информация об исключении. быть брошенным в методе onException Can.