EasyExcel使用
Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
文档地址:https://alibaba-easyexcel.github.io/index.html
大家也可以根据文档参考开发
下面这个导入导出示例是在真实的项目环境下参考的
导入示例:
也就是读Excel中的数据,这里需要定义监听器
1、导入依赖
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
2、定义监听器
public class DictListener extends AnalysisEventListener<DictEeVo> {
private DictMapper dictMapper;
public DictListener(DictMapper dictMapper) {
this.dictMapper = dictMapper;
}
//一行一行的读取
@Override
public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
//调用方法把读取到的数据添加到数据库中去
Dict dict = new Dict();
BeanUtils.copyProperties(dictEeVo,dict);
dictMapper.insert(dict);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
3、定义数据接口
//数据列表的导入功能
void importData(MultipartFile file);
4、实现接口
//数据列表的导入功能
@Override
@CacheEvict(value = "dict", allEntries=true)
public void importData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(dictMapper)).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
5、controller层调用接口
//导入数据功能
@ApiOperation("导入数据")
@PostMapping("/importData")
public Result<?> importData(MultipartFile file){
dictService.importData(file);
return Result.ok();
}
注:上面监听器的实现是继承了AnalysisEventListener,它是EasyExcel框架中用于读取Excel文件的监听器类。通过继承AnalysisEventListener
并实现其中的方法,可以自定义处理Excel文件中的每一行数据,实现灵活的数据读取和处理逻辑。
数据处理,通过重写invoke方法,可以对每一行读取的数据进行处理。大家也可以点进去看一下这部分的源码。
导出示例:
从数据库或者其他地方导出数据到Excel中,本质上是从数据库中把全部数据查出来,然后再写进Excel
1、依赖同上
2、定义数据接口
//数据列表的导出功能
void exportData(HttpServletResponse response);
3、接口实现(这只是项目中的实际需求,大家可以根据实际修改)
@Override
public void exportData(HttpServletResponse response) {
try {
//指定响应数据的格式
response.setContentType("application/vnd.ms-excel");
//防止乱码
response.setCharacterEncoding("utf-8");
//文件名
String fileName = URLEncoder.encode( "数据字典","utf-8");
//告诉浏览器以附件的方式打开(下载)
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
List<Dict> dictList = baseMapper.selectList(null);
//需要接收的是DictEvo类型 但是原来查的是Dict类型 需要进行一个转换
//转成vo对象 然后再转入dictEeVoList中
List<DictEeVo> voList = new ArrayList<>();
for (Dict dict : dictList) {
DictEeVo vo = new DictEeVo();
//两者的属性名是相同的 使用工具类直接转
BeanUtils.copyProperties(dict,vo);
voList.add(vo);
}
EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(voList);
} catch (IOException e) {
e.printStackTrace();
}
}
4、controller调用
@ApiOperation("导出数据")
@GetMapping(value = "/exportData")
public void exportData(HttpServletResponse response) {
dictService.exportData(response);
}