EasyExcel实现表格导入导出
1.简介
Java领域解析,生成Excel比较有名的框架有Apache poi,jxl等,但他们都存在一个严重的问题就是非常的耗内存,如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc.
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 github地址:https://github.com/alibaba/easyexcel
2.入门案例
2.1.创建maven工程
2.2.导入pom依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.0-beta2</version> </dependency> |
准备表格
2.3.学生实体类
package cn.demo.domain;
import com.alibaba.excel.annotation.ExcelProperty;
import java.util.Date;
/** * 学生实体类 */ public class Student { /** * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据 */ @ExcelProperty("姓名") private String name; @ExcelProperty("性别") private String sex; @ExcelProperty("出生日期") private Date birthDate;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSex() { return sex; }
public void setSex(String sex) { this.sex = sex; }
public Date getBirthDate() { return birthDate; }
public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", birthDate=" + birthDate + '}'; } } |
2.4.测试读取excel
package cn.demo;
import cn.demo.domain.Student; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.PageReadListener; import com.alibaba.excel.read.listener.ReadListener; import org.junit.Test;
import java.io.File;
/** * 测试导入导出 */ public class EasyExcelTest {
/** * 测试读取 * @throws Exception */ @Test public void testRead() throws Exception{ // 写法1:JDK8+ // 读取的文件 String fileName = "d:/test.xls"; // 这里需要指定读用哪个class去读,然后读取第一个sheet 指定headRowNumber参数,如果不传默认是1 然后读文件流会自动关闭 EasyExcel.read(fileName, Student.class, new PageReadListener<Student>(dataList -> { dataList.forEach(System.out::println); })).sheet().headRowNumber(2).doRead(); // 写法2: 使用匿名内部类 EasyExcel.read(fileName, Student.class, new ReadListener<Student>() { // 一行行读取excel内容 @Override public void invoke(Student student, AnalysisContext analysisContext) { System.out.println("读取到的数据:"+student); } // 读取完成之后 @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { System.out.println("解析完成...."); } }).sheet().headRowNumber(2).doRead(); } } |
测试读取结果
2.5.测试写入Excel
准备数据
/** * 模拟数据 * @return */ private List<Student> data() { List<Student> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { Student data = new Student(); data.setName("王天霸"+i); data.setSex(i%2==0?"男":"女"); data.setBirthDate(new Date()); list.add(data); } return list; } |
测试写入
/** * 测试写入 * @throws Exception */ @Test public void testWrite() throws Exception{ // 写法1:JDK8+ // 输出的文件名 String fileName = "d:/"+System.currentTimeMillis() + ".xlsx"; // 这里需要指定写用哪个class去写,然后写到第一个sheet,名字为模板然后文件流会自动关闭 EasyExcel.write(fileName, Student.class) .sheet("模板") .doWrite(() -> { // 分页查询数据 return data(); }); // 写法2 EasyExcel.write(fileName, Student.class).sheet("模板").doWrite(data()); } |
测试写入结果
3. 在web中的运用
3.1.web中的读与写
新建一个springboot项目,过程略过
导入相关依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!--引入easyexcel依赖--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.0-beta2</version> </dependency> |
控制层代码
package cn.demo.web.controller;
import cn.demo.domain.Student; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Date; import java.util.List;
/** * 导入导出Controller */ @RestController public class ExcelController {
/** * 上传excel * @param file * @return * @throws IOException */ @PostMapping("/upload") public String upload(@RequestParam("file")MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), Student.class, new ReadListener<Student>() {
@Override public void invoke(Student student, AnalysisContext analysisContext) { System.out.println("读取到的数据:"+student); // 这里可以做保存数据库操作 }
@Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { System.out.println("解析完成...."); } }).sheet().doRead(); return "success"; }
/** * 导出excel * @param response * @throws IOException */ @GetMapping("/download") public void download(HttpServletResponse response) throws IOException { // 这里注意请直接用浏览器或者用postman response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), Student.class).sheet("模板").doWrite(data()); }
/** * 模拟数据 * @return */ private List<Student> data() { List<Student> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { Student data = new Student(); data.setName("王天霸"+i); data.setSex(i%2==0?"男":"女"); data.setBirthDate(new Date()); list.add(data); } return list; } } |
测试导入导出
导入用postman测试
导出直接在浏览器上测试,输入地址即可下载