在管理一个系统时,总会有许多的数据,为了方便浏览查看数据,系统总会提供「导出Excel」的功能;有导出就有导入,在要向数据库中插入大量的数据时,我们向程序提供准备好的 Excel,然后程序读取表格内容,并将数据添加到数据库中。
实现这个「导入/导出 Excel」的功能也不复杂,我们使用第三方的类库即可实现。
1.技术选型
能够实现「导入/导出 Excel」的第三方常用类库有 Apache poi、Java Excel(JXL)和阿里巴巴开源的 Easyexcel 等。这么多类库该怎么选呢?在这里我给大家推荐阿里巴巴开源的「Easyexcel」。
-
性能对比
poi 和 jxl 对内存的消耗很大,在处理大批量的数据时,容易造成内存溢出。比如处理一个 3M 的 Excel,poi 和 jxl 可能需要上百兆的内存,但 easyexcel 可能只需要几百或几千 KB(内存消耗对比有些夸张)。在性能这一块,Excel 完全是吊打 poi 和 jxl。 -
学习复杂度对比
poi,在学习它的时候,理解起来不难,就是操作的时候太特么的难了。因为 poi 需要自己处理数据,还有复杂的表格样式,就光是处理数据这一款就很头疼了。等你写好所有的代码,没有几百行,你是实现不了的。反观 easyexcel。它能自己处理数据,表格格式也简单,即使是小白也很容易上手。在学习复杂的这块也吊打 poi,而 jxl 我没了解,但多半也是被吊打。
2.easyexc拟解决的问题
- Excel读写时内存溢出
- 使用简单
- Excel格式解析
3.工作原理
添加maven依赖
<!-- EasyExcel核心文件 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
</dependency>
<!-- fastjson依赖包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<!-- 解析上传数据 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- slf4j/log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
Excel下载
- HTML
<a href="tAccount/DownLoadExcel">下载</a>
- 封装数据的Java类
public class User {
@ExcelProperty("用户编号")
private Integer userId;
@ExcelProperty("用户名称")
private String userName;
@ExcelProperty("用户性别")
private String gender;
@ExcelProperty("创建时间")
private Date createTime;
}
- 下载操作
@GetMapping("DownLoadExcel")
public void dopost(HttpServletRequest request, HttpServletResponse response) throws IOException {
/**
* EasyExcel下载步骤
*/
//设置响应头
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
//设置防止文件名中文乱码
String fileName = URLEncoder.encode("user1中文文件名","utf-8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//构建写入到Excel中的数据(此数据可以从数据库中获取)
List<User> users = new ArrayList<>();
User user1 = new User(1001, "李四1", "男", new Date());
User user2 = new User(1002, "李四2", "男", new Date());
User user3 = new User(1003, "李四3", "男", new Date());
users.add(user1);
users.add(user2);
users.add(user3);
EasyExcel.write(response.getOutputStream(),User.class).sheet("用户信息").doWrite(users);
}
Excel上传
- 前端页面
<form action="tAccount/UploadExcelServlet" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上传">
</form>
- 接收从Excel中获取到的数据
public class User {
@ExcelProperty("用户编号")
private Integer userId;
@ExcelProperty("用户名称")
private String userName;
@ExcelProperty("用户性别")
private String gender;
@ExcelProperty("创建时间")
private Date createTime;
}
- 上传操作
@PostMapping("UploadExcelServlet")
public void doposts(HttpServletRequest req, HttpServletResponse resp)throws IOException{
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//设置单个文件为3M
fileUpload.setFileSizeMax(1024*1024*3);
//总文件大小为30M
fileUpload.setSizeMax(1024*1024*3*10);
try {
List<FileItem> list = fileUpload.parseRequest(req);
for (FileItem fileItem : list) {
//判断是否为附件
if(!fileItem.isFormField()) {
//是附件
InputStream inputStream = fileItem.getInputStream();
EasyExcel.read(inputStream,User.class,new AnalysisEventListener<User>() {
@Override
public void doAfterAllAnalysed(AnalysisContext arg0) {
System.out.println("Excel全部读完被执行......");
}
@Override
public void invoke(User data, AnalysisContext arg1) {
//读完一行就执行一次(调用数据库进行插入操作)
System.out.println("解析一行: "+data);
}
}).sheet().doRead();
}else {
//普通表单
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
//上传完成进行转发或者重定向
}