easyexcel官网地址:https://easyexcel.opensource.alibaba.com/
1、在pom.xml文件中导入easyexcel的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.0</version>
</dependency>
2、定义一个实体类来封装每一行的数据
@Data
public class CategoryExcel {
@ExcelProperty(value = "id" ,index = 0)
private Long id;
@ExcelProperty(value = "名称" ,index = 1)
private String name;
@ExcelProperty(value = "图片url" ,index = 2)
private String imageUrl ;
@ExcelProperty(value = "上级id" ,index = 3)
private Long parentId;
@ExcelProperty(value = "状态" ,index = 4)
private Integer status;
@ExcelProperty(value = "排序" ,index = 5)
private Integer orderNum;
}
3、导出主要业务
try {
// 设置响应结果类型
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码
String fileName = URLEncoder.encode("分类数据", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
// 查询数据库中的数据
List<Category> categoryList = categoryMapper.selectAll();
List<CategoryExcelVo> categoryExcelVoList = new ArrayList<>(categoryList.size());
// 写出数据到浏览器端
EasyExcel.write(response.getOutputStream(), CategoryExcel.class).sheet("分类数据").doWrite(categoryList);
} catch (IOException e) {
e.printStackTrace();
}
4、导入功能
4.1 定义一个监听器
注意:Listener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去。
- invoke()用于处理Excel中一行解析形成的POJO对象,解析过程由EasyExcel根据POJO字段上的注解自动完成。
- doAfterAllAnalysed()在invoke方法处理完整个Sheet中的所有数据之后调用,本文中用于将最后一批缓存的数据入库。
public class ExcelListener<T> extends AnalysisEventListener<T> {
/**
每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 100;
/**
* 缓存的数据
*/
private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
//获取mapper对象
private CategoryMapper categoryMapper;
//ExcelListener不能被spring管理,所以通过构造方法进行注入
public ExcelListener(CategoryMapper categoryMapper) {
this.categoryMapper = categoryMapper;
}
// 每解析一行数据就会调用一次该方法
@Override
public void invoke(T o, AnalysisContext analysisContext) {
CategoryExcel data = (CategoryExcel)o;
cachedDataList.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// excel解析完毕以后需要执行的代码
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
}
private void saveData() {
categoryMapper.batchInsert(cachedDataList);
}
}
4.2 业务层代码实现
public void importData(MultipartFile file) {
try {
//创建监听器对象,传递mapper对象
ExcelListener<CategoryExcel> excelListener = new ExcelListener<>(categoryMapper);
//调用read方法读取excel数据
EasyExcel.read(file.getInputStream(),
CategoryExcel.class,
excelListener).sheet().doRead();
} catch (IOException e) {
throw new GuiguException(ResultCodeEnum.DATA_ERROR);
}
}