阿里巴巴Excel读写组件EasyExcel入门实践
前言
最近在开发一个运营端的系统,而运营端系统,经常有数据通过Excel文件上传、导出的功能,也就是涉及到Excel文件的读写操作。
我们都知道,在Java开发中,Excel相关的操作,我们都使用POI进行开发。但是Excel文件的读写,经常有这么一个场景,就是涉及到大量数据的读写,使用POI经常会遇到机器内存使用率过高的问题,而EasyExcel就很好地解决了这个问题。Excel导出
我们先进行简单的Excel数据导出实践。
1.Maven依赖
可以到mvnrepository上搜索EasyExcel,选择一个最新的版本即可。 com.alibaba easyexcel 3.1.3
笔者采用的,是目前最新的3.1.3版本,生产环境还是建议使用稳定版。
2.MySQL数据
生产环境Excel数据导出,一般都是从MySQL数据库中获取。为了贴近正常场景,我们事先在MySQL上存储部分数据,然后试着将这些数据通过Excel格式导出。
3.Excel对象映射
EasyExcel有一个很不错的设计,就是Excel文件的列,是和Java对象的字段,一一对应的。这点和操作MySQL、JPA一样,毕竟Excel也可以理解为一个关系数据库文件。package com.example.springbooteasyexcel.domain; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import java.math.BigDecimal; import java.util.Date; /** * 商品信息 * * @author hongcunlin */ @Entity @Data @Table public class ProductInfo { /** * 自增ID */ @Id @GeneratedValue @ExcelProperty("商品id") private Long id; /** * 商品名 */ @ExcelProperty("商品名称") private String name; /** * 商品价格 */ @ExcelProperty("商品价格") private BigDecimal price; /** * 创建时间 */ @ExcelProperty("商品创建时间") private Date createTime = new Date(); }
通过@ExcelProperty注解,是Excel列和Java对象中的字段对应起来。
4.Excel导出HTTP接口
通过JPA将数据从MySQL中读取出来,通过EasyExcel将数据通过Excel文件导出。package com.example.springbooteasyexcel.controller; import com.alibaba.excel.EasyExcel; import com.example.springbooteasyexcel.domain.ProductInfo; import com.example.springbooteasyexcel.repository.ProductInfoRepository; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; /** * Excel读写HTTP接口 * * @author hongcunlin */ @RestController @RequestMapping("/productInfoController") public class ProductInfoController { /** * 商品信息repository */ @Resource private ProductInfoRepository productInfoRepository; /** * Excel数据导出 * * @param response excel文件 * @throws IOException e */ @GetMapping("/exportProductInfo") public void exportProductInfo(HttpServletResponse response) throws IOException { List productInfoList = productInfoRepository.findAll(); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-disposition", "attachment;filename=test.xlsx"); EasyExcel.write(response.getOutputStream(), ProductInfo.class).sheet().doWrite(productInfoList); } }
Excel导出的API使用起来还是很简单,它导出完Excel数据,还会帮你关闭文件流,这点很关键。
5.Excel导出测试
我们访问我上面编写的接口,即可得到我们想要的Excel文件了,内容如下:
符合我们的预期。Excel上传
Excel上传写起来,稍微复杂一点点,主要是多了一个Excel读取的监听器
1.Excel监听器package com.example.springbooteasyexcel.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.metadata.CellExtra; import com.example.springbooteasyexcel.domain.ProductInfo; import lombok.Getter; import java.util.ArrayList; import java.util.List; /** * 商品列表导出监听器 * * @author hongcunlin */ @Getter public class ProductInfoListener extends AnalysisEventListener { /** * 商品列表 */ private final List productInfoList = new ArrayList<>(); @Override public void onException(Exception exception, AnalysisContext context) throws Exception { super.onException(exception, context); } @Override public void invoke(ProductInfo productInfo, AnalysisContext analysisContext) { productInfoList.add(productInfo); } @Override public void extra(CellExtra extra, AnalysisContext context) { super.extra(extra, context); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } @Override public boolean hasNext(AnalysisContext context) { return super.hasNext(context); } }
主要继承AnalysisEventListener父类,并实现了相关方法。主要是invoke方法,里边是Excel数据读取之后的处理逻辑。
2.Excel文件上传HTTP接口package com.example.springbooteasyexcel.controller; import com.alibaba.excel.EasyExcel; import com.example.springbooteasyexcel.domain.ProductInfo; import com.example.springbooteasyexcel.listener.ProductInfoListener; import com.example.springbooteasyexcel.repository.ProductInfoRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; /** * Excel读写HTTP接口 * * @author hongcunlin */ @Slf4j @RestController @RequestMapping("/productInfoController") public class ProductInfoController { /** * 商品信息repository */ @Resource private ProductInfoRepository productInfoRepository; /** * Excel数据上传 * * @param file excel文件 * @throws IOException e */ @PostMapping(value = "/uploadProductInfo", headers = "content-type=multipart/form-data") public void uploadProductInfo(MultipartFile file) throws IOException { ProductInfoListener productInfoListener = new ProductInfoListener(); EasyExcel.read(file.getInputStream(), ProductInfo.class, productInfoListener).sheet().doRead(); productInfoRepository.saveAll(productInfoListener.getProductInfoList()); } }
和Excel文件读取差不多,也是很简洁的API,不再赘述。
3.准备Excel数据
我们编写2条Excel数据,后面用于文件的上传
4.上传测试
我们通过Swagger2提供的界面,进行Excel文件的上传测试。
可以看到,我们上传的Excel文件中的数据,已经导入数据库中了,符合我们的预期。其他
本文通过EasyExcel,轻松的进行了Excel文件的读取。本文是入门实践篇,后面关于Excel更多的细节,笔者有空再另起文章。