excel导入导出

1. 导入依赖

xml 复制代码
<dependency>
    <groupId>com.alibaba.easyexcel</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>

2. 定义实体类

java 复制代码
@Data
@ColumnWidth(25)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ImportConfigDTO {

    @ExcelProperty("类型")
    @ColumnWidth(15)
    private String type;

    @ExcelProperty("故障名")
    @ColumnWidth(15)
    private String name;

    @ExcelProperty("故障码")
    @ColumnWidth(15)
    private String faultCode;

    @ExcelProperty("描述")
    @ColumnWidth(15)
    private String description;
}

3. Controller类

java 复制代码
@Slf4j
@RestController
public class ExportConfigController {

    @Autowired
    private ImportConfigService importConfigService;

    @PostMapping("/api/v1/importConfigTemplate")
    public ResponseEntity<String> importConfigTemplate(MultipartFile file) {
        importDtcConfigService.importDtoConfigTemplate(file);
        return ResponseEntity.ok("success");
    }

    @PostMapping("/api/v1/import-config")
    public ResponseEntity<String> importConfig(MultipartFile file) {
        String filename = file.getOriginalFilename();
        if (StringUtil.isBlank(filename)) {
            throw new RuntimeException("请上传文件!");
        }
        if ((!StringUtils.endsWithIgnoreCase(filename, ".xls") && !StringUtils.endsWithIgnoreCase(filename, ".xlsx"))) {
            throw new RuntimeException("请上传正确的excel文件!");
        }
        InputStream inputStream;
        try {
            ConfigImportListener importListener = new ConfigImportListener(importConfigService);
            inputStream = new BufferedInputStream(file.getInputStream());
            ExcelReaderBuilder builder = EasyExcel.read(inputStream, ImportConfigDTO.class, importListener);
            builder.doReadAll();
        } catch (IOException e) {
            throw new RuntimeException("excel文件上传出现错误" + e.getMessage());
        }
        return ResponseEntity.ok("操作成功");
    }

    @SneakyThrows
    @GetMapping("/api/v1/export-config")
    public void exportConfig(HttpServletResponse response) {
        List<ImportConfigDTO> list = importConfigService.findAll();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        String fileName = URLEncoder.encode("配置数据导出", StandardCharsets.UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ImportConfigDTO.class).sheet("配置数据表").doWrite(list);
    }

    @SneakyThrows
    @GetMapping("/api/v1/export-template")
    public void exportTemplate(HttpServletResponse response) {
        List<ImportConfigDTO> list = new ArrayList<>();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        String fileName = URLEncoder.encode("配置数据模板", StandardCharsets.UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ImportConfigDTO.class).sheet("配置数据表").doWrite(list);
    }
}

4. 两种监听类定义方式

  • 方式一:调用保存方法
java 复制代码
@Data
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class ConfigImportListener extends AnalysisEventListener<ImportConfigDTO> {

	/**
	 * 默认每隔3000条存储数据库
	 */
	private int batchCount = 3000;
	/**
	 * 缓存的数据列表
	 */
	private List<ImportConfigDTO> list = new ArrayList<>();

	private final ImportConfigService importConfigService;

	@Override
	public void invoke(ImportConfigDTO data, AnalysisContext context) {
		list.add(data);
		// 达到BATCH_COUNT,则调用importer方法入库,防止数据几万条数据在内存,容易OOM
		if (list.size() >= batchCount) {
			// 调用importer方法
			importConfigService.uploadExcelDtoConfig(list);
			// 存储完成清理list
			list.clear();
		}
	}

	@Override
	public void doAfterAllAnalysed(AnalysisContext analysisContext) {
		// 调用importer方法
		importConfigService.uploadExcelDtoConfig(list);
		// 存储完成清理list
		list.clear();
	}

}
  • 方式二:只做数据接收
java 复制代码
@Data
@EqualsAndHashCode(callSuper = true)
public class ConfigListener extends AnalysisEventListener<ImportConfigDTO> {

    List<ImportConfigDTO> list = Lists.newLinkedList();

    List<ExcelDataConvertException> listException = new ArrayList<>();

    Map<Integer, String> excelHeadMap = new HashMap<>(10);

    @Override
    public void invoke(ImportConfigDTO data, AnalysisContext analysisContext) {
        list.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        excelHeadMap = headMap;
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
    }
}

5. Excel工具类

java 复制代码
@Slf4j
public class ExcelUtils {

    public static final long MAX_SIZE = 10 * 1024 * 1024;


    /**
     * 用于读取excel
     * @param file                  文件参数
     * @param importClass           导入对象class
     * @param analysisEventListener 分析事件监听器
     */
    public static void readExcel(MultipartFile file, Class<?> importClass, AnalysisEventListener<?> analysisEventListener) {
        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        try(InputStream inputStream = file.getInputStream()) {
            if (file.getSize() > MAX_SIZE) {
                throw new RuntimeException("The maximum file size allowed for upload is 10MB 上传文件最大允许上传10MB");
            }
            String fileName = file.getOriginalFilename();
            if (fileName == null || !(fileName.endsWith(".xls") || fileName.endsWith(".xlsx"))) {
                throw new RuntimeException("The uploaded file format is incorrect, it must be in. xls or. xlsx format 上传文件格式不正确,必须是.xls或.xlsx格式");
            }
            EasyExcel.read(inputStream, importClass, analysisEventListener).sheet().doRead();
        } catch (IOException e) {
            throw new RuntimeException("excel文件上传出现错误" + e.getMessage());
        }
    }
}

6. Service类

java 复制代码
@Slf4j
@Service
public class ImportConfigService {

    @Autowired
    private ConfigMapper configMapper;

    public void importDtoConfigTemplate(MultipartFile multipartFile) {
        ConfigListener configListener = new ConfigListener();
        //读取excel
        ExcelUtils.readExcel(multipartFile, ImportConfigDTO.class, configListener);

        List<ImportConfigDTO> configImportList = configListener.getList();

        if (CollectionUtil.isEmpty(configImportList)) {
            throw new RuntimeException("Upload file is empty 上传文件为空");
        }
        List<ExcelDataConvertException> listException = configListener.getListException();
        Set<String> infoSet = listException.stream()
                .map(e -> "第" + (e.getRowIndex() + 1) + "行,第" + (e.getColumnIndex() + 1) + "列")
                .collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(infoSet)) {
            uploadExcelDtoConfig(configImportList);
        } else {
            throw new RuntimeException(String.join(";", infoSet));
        }
    }

    public void uploadExcelDtoConfig(List<ImportConfigDTO> importConfigDTOList) {
        List<ConfigPO> configPOList = new ArrayList<>();
        for (ImportConfigDTO importConfigDTO : importConfigDTOList) {
            ConfigPO configPO = new ConfigPO();
            configPO.setId(IdWorker.nextId());
            configPO.setType(importConfigDTO.getType());
            configPO.setName(importConfigDTO.getName());
            configPO.setFaultCode(importConfigDTO.getFaultCode());
            configPO.setDescription(importConfigDTO.getDescription());
            configPO.setCreatedAt(LocalDateTime.now());
            configPO.setCreatedBy("system");
            configPO.setUpdatedAt(LocalDateTime.now());
            configPO.setUpdatedBy("system");
            configPOList.add(configPO);
        }
        if (CollectionUtil.isNotEmpty(configPOList)) {
            configMapper.batchInsert(configPOList);
        }
    }

    public List<ImportConfigDTO> findAll() {
        return configMapper.findAll();
    }
}
相关推荐
Elieal43 分钟前
SpringBoot 数据层开发与企业信息管理系统实战
java·spring boot·后端
识君啊43 分钟前
MyBatis-Plus 逻辑删除导致唯一索引冲突的解决方案
java·spring boot·mybatis·mybatis-plus·唯一索引·逻辑删除
Coder_Boy_1 小时前
Java开发者破局指南:跳出内卷,借AI赋能,搭建系统化知识体系
java·开发语言·人工智能·spring boot·后端·spring
热爱生活的五柒1 小时前
wps office/word 表格左对齐后 文字前仍有空白,如何解决
excel
Aric_Jones1 小时前
idea使用.env运行SpringBoot项目
java·spring boot·intellij-idea
代码栈上的思考2 小时前
SpringBoot 拦截器
java·spring boot·spring
jbtianci2 小时前
Spring Boot管理用户数据
java·spring boot·后端
编程彩机2 小时前
互联网大厂Java面试:从Jakarta EE到微服务架构的技术场景深度解读
spring boot·分布式事务·微服务架构·java面试·jakarta ee
biyezuopinvip2 小时前
基于Spring Boot的企业网盘的设计与实现(毕业论文)
java·spring boot·vue·毕业设计·论文·毕业论文·企业网盘的设计与实现
程序员敲代码吗2 小时前
在Excel中快速进行精确数据查找的方法
excel