前言
最近在开发一个运营端的系统,而运营端系统,经常有数据通过Excel文件上传、导出的功能,也就是涉及到Excel文件的读写操作。
我们都知道,在Java开发中,Excel相关的操作,我们都使用POI进行开发。但是Excel文件的读写,经常有这么一个场景,就是涉及到大量数据的读写,使用POI经常会遇到机器内存使用率过高的问题,而EasyExcel就很好地解决了这个问题。
Excel导出
我们先进行简单的Excel数据导出实践。
1.Maven依赖
可以到mvnrepository上搜索EasyExcel,选择一个最新的版本即可。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.3</version>
</dependency>
笔者采用的,是目前最新的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<ProductInfo> {
/**
* 商品列表
*/
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文件中的数据,已经导入数据库中了,符合我们的预期。
内容出处:,
声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。文章链接:http://www.yixao.com/procedure/30229.html