在管理一个系统时,总会有许多的数据,为了方便浏览查看数据,系统总会提供「导出Excel」的功能;有导出就有导入,在要向数据库中插入大量的数据时,我们向程序提供准备好的 Excel,然后程序读取表格内容,并将数据添加到数据库中。
实现这个「导入/导出 Excel」的功能也不复杂,我们使用第三方的类库即可实现。
技术选型
能够实现「导入/导出 Excel」的第三方常用类库有 Apache poi、Java Excel(JXL)和阿里巴巴开源的 Easyexcel 等。这么多类库该怎么选呢?在这里我给大家推荐阿里巴巴开源的「Easyexcel」。
-
性能对比
poi 和 jxl 对内存的消耗很大,在处理大批量的数据时,容易造成内存溢出。比如处理一个 3M 的 Excel,poi 和 jxl 可能需要上百兆的内存,但 easyexcel 可能只需要几百或几千 KB(内存消耗对比有些夸张)。在性能这一块,Excel 完全是吊打 poi 和 jxl。 -
学习复杂度对比
我最开始使用的是 poi。在学习它的时候,理解起来不难,就是操作的时候太特么的难了。因为 poi 需要自己处理数据,还有复杂的表格样式,就光是处理数据这一款就很头疼了。等你写好所有的代码,没有几百行,你是实现不了的。反观 easyexcel。它能自己处理数据,表格格式也简单,即使是小白也很容易上手。在学习复杂的这块也吊打 poi,而 jxl 我没了解,但多半也是被吊打。
项目结构
项目结构
pom.xml
在项目中需要额外添加 EasyExcel 和文件上传的依赖(需要上传 Excel)。需要注意的时,EasyExcel 和 Apache poi 存在冲突,所以需要在项目中去除 poi 的依赖,然而我们并没有在项目引入 poi 的依赖,又怎么会又 poi 呢?这是因为在我们的项目中,有其它包依赖于 poi,而我们就需要将其找出来,并去除其中的 poi 依赖。最简单的方法就是一个个试。
.........
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><!-- 去除 poi --><exclusions><exclusion><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></exclusion></exclusions><version>${org.slf4j-version}</version>
</dependency>
<!-- 文件上传依赖 -->
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>1.3.2</version>
</dependency>
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.2.1</version>
</dependency>
<!--Alibaba-Excel-->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>1.1.2-beat1</version>
</dependency>
ExcelListener
使用 EasyExcel,我们需要继承 AnalysisEventListener
。
public class ExcelListener extends AnalysisEventListener {//可以通过实例获取该值private List<Object> datas = new ArrayList<Object>();public void invoke(Object o, AnalysisContext analysisContext) {datas.add(o);//数据存储到list,供批量处理,或后续自己业务逻辑处理。doSomething(o);//根据自己业务做处理}private void doSomething(Object object) {//1、入库调用接口}public List<Object> getDatas() {return datas;}public void setDatas(List<Object> datas) {this.datas = datas;}public void doAfterAllAnalysed(AnalysisContext analysisContext) {// datas.clear();//解析结束销毁不用的资源}
}
其中, invoke()
和 doAfterAllAnalysed()
是必须实现的方法。
在 invoke()
中,我们将数据封装到 list
中,再在控制器中,通过 getter()
方法获取数据,这样我们就可以获取到 easyexcel
帮我们解析好的数据,再将数据进行类型转化,这样,我们就可以对数据进行写入操作。
Category
这是一个实体类。我们导出 Excel 时,有时需要表头,如果需要表头,我们就可以在相应的实体类中加入 @ExcelProperty(value = "id", index = 0)
注解,并且继承 BaseRowModel
。其中 value 代表在导出 Excel 时,该字段对应的表头名称;index 代表该字段对应的表头位置。
public class Catagory extends BaseRowModel {@ExcelProperty(value = "id", index = 0)private Integer id;@ExcelProperty(value = "name", index = 1)private String name;.........
}
ExcleController
作为程序的控制器,其中包含 导入/导出 Excel 的 @RequestMapping
。
/expor
这是导出 Excel 的控制器,导出的思路也很简单。
-
添加响应头信息;
-
添加 ExcelWriter;
-
添加 Sheet(表单);
-
添加数据;
-
输出。
@RequestMapping("/expor")
public String exporExcel(HttpServletResponse response) throws IOException {ExcelWriter writer = null;OutputStream outputStream = response.getOutputStream();try {//添加响应头信息response.setHeader("Content-disposition", "attachment; filename=" + "catagory.xls");response.setContentType("application/msexcel;charset=UTF-8");//设置类型response.setHeader("Pragma", "No-cache");//设置头response.setHeader("Cache-Control", "no-cache");//设置头response.setDateHeader("Expires", 0);//设置日期头//实例化 ExcelWriterwriter = new ExcelWriter(outputStream, ExcelTypeEnum.XLS, true);//实例化表单Sheet sheet = new Sheet(1, 0, Catagory.class);sheet.setSheetName("目录");//获取数据List<Catagory> catagoryList = excleService.findAll();//输出writer.write(catagoryList, sheet);writer.finish();outputStream.flush();} catch (IOException e) {e.printStackTrace();} finally {try {response.getOutputStream().close();} catch (IOException e) {e.printStackTrace();}}return "index";
}
/import
这是导入 Excel 的控制器,实现思路与导入的思路类似,不过这个不需添加响应头信息。
-
实例化 ExcelListener;
-
实例化 ExcelReader;
-
读取表格信息;
-
向数据库插入数据。
@RequestMapping("/import")
public String importExcel(@RequestParam("file") MultipartFile file) throws IOException {InputStream inputStream = file.getInputStream();//实例化实现了AnalysisEventListener接口的类ExcelListener listener = new ExcelListener();//传入参数ExcelReader excelReader = new ExcelReader(inputStream, ExcelTypeEnum.XLS, null, listener);//读取信息excelReader.read(new Sheet(1, 1, Catagory.class));//获取数据List<Object> list = listener.getDatas();List<Catagory> catagoryList = new ArrayList<Catagory>();Catagory catagory = new Catagory();//转换数据类型,并插入到数据库for (int i = 0; i < list.size(); i++) {catagory = (Catagory) list.get(i);catagoryMapper.insertCategory(catagory);}return "index";
}
JSP
涉及到文件的上传,所以在 JSP 中,需要注意 form
的 enctype
类型。不然,你在上传文件时会一直报错。
<form action="${pageContext.request.contextPath}/import", method="post", enctype="multipart/form-data"><input type="file" name="file"/><input type="submit">
</form>
写到这里,程序的主要代码也看的差不多了,其它的代码请查看项目源码。
导出 Excel 效果
导出效果
JSP 效果
jsp页面
点击获取项目源码
作者:Xuuuuucong
链接:https://www.jianshu.com/p/78cc1729fbd1
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。