EasyExcel读写、模板填充、Web上传下载入门到实战全指南

 更新时间:2026年01月26日 08:24:04   作者:五阿哥永琪  
EasyExcel类是一套基于Java的开源Excel解析工具类,相较于传统的框架如Apache poi、jxl等更加快速、简洁,还可以解决大文件内存溢出问题,这篇文章主要介绍了EasyExcel读写、模板填充、Web上传下载入门到实战的相关资料,需要的朋友可以参考下

EasyExcel 是阿里巴巴开源的一款 基于 Java 的高性能、简单易用的 Excel 读写工具库,专注于解决使用 Apache POI(Java 操作 Excel 的底层库)时常见的 内存溢出(OOM)API 复杂 问题。

一、 主要功能

1. 读 Excel(支持 .xls / .xlsx)

  • 按行读取,自动映射到 Java 对象
  • 支持读取表头、数据、异常处理
  • 可监听每行数据(适合大数据量)
EasyExcel.read(fileName, DemoData.class, new MyReadListener())
         .sheet()
         .doRead();

2. 写 Excel

  • 自动根据对象字段生成表头和数据
  • 支持大数据量分批写入(百万行无压力)
  • 可指定列宽、行高、样式等
EasyExcel.write(fileName, DemoData.class)
         .sheet("Sheet1")
         .doWrite(dataList);

3. Excel 填充(模板填充)

  • 提供 Excel 模板(带占位符如 {name}
  • 自动填充数据,适合生成报表、证书等
EasyExcel.write(out, DemoData.class)
         .withTemplate(templateFile)
         .sheet()
         .doFill(data);

4. 丰富的注解支持

  • @ExcelProperty("姓名"):指定列名
  • @ColumnWidth(20):设置列宽
  • @DateTimeFormat("yyyy-MM-dd"):日期格式化
  • @NumberFormat("#,##0.00"):数字格式化
  • @ExcelIgnore:忽略字段
public class User {
    @ExcelProperty("用户姓名")
    private String name;

    @ExcelProperty("注册时间")
    @DateTimeFormat("yyyy年MM月dd日")
    private Date registerTime;
}

二、 快速开始

1. 引入依赖

<!--Lombok依赖-->  
<dependency>  
    <groupId>org.projectlombok</groupId>  
    <artifactId>lombok</artifactId>  
    <optional>true</optional>  
</dependency>  
<!--easyexcel依赖-->  
<dependency>  
    <groupId>com.alibaba</groupId>  
    <artifactId>easyexcel</artifactId>  
    <version>4.0.3</version>  
</dependency>  
<!--fastjson依赖-->  
<dependency>  
    <groupId>com.alibaba</groupId>  
    <artifactId>fastjson</artifactId>  
    <version>2.0.57</version>  
</dependency>

2. 写实体类

package com.nuc.demoexcel.entity;  
  
import com.alibaba.excel.annotation.ExcelIgnore;  
import com.alibaba.excel.annotation.ExcelProperty;  
import com.alibaba.excel.annotation.write.style.ColumnWidth;  
import com.alibaba.excel.annotation.write.style.HeadRowHeight;  
import com.alibaba.fastjson.annotation.JSONField;  
import lombok.Data;  
  
import java.util.Date;  
  
@Data  
@HeadRowHeight(20)  
@ColumnWidth(20)  
public class DemoDate {  
    @ExcelProperty("字符串标题")  
    private String name;  
    @ExcelProperty("日期标题")  
    @JSONField(format = "yyyy-MM-dd,HH:mm:ss") // 格式化日期 没有注解会默认转成时间戳  
    private Date date;  
    @ExcelProperty("数字标题")  
    private Double doubleData;  
    @ExcelIgnore  
    private String ignore;  
}

3. Excel读取

读取常用有三种方法

  • 这是我提前准备好的excel文件

方法一:

有封装的实体类
.head(DemoData.class)封装
结果用List<DemoData>

/**  
 * 测试读1  
 * 有封装的实体类  
 */  
@Test  
void readExcel1() {  
    System.out.println("测试");  
    List<DemoDate> list = EasyExcel.read("D:\\测试\\demo.xlsx").head(DemoDate.class).sheet().doReadSync();  
    list.forEach(data ->{  
        String jsonString = JSON.toJSONString(data);  
        log.info("读取到数据{}",jsonString);  
    });  
}
  • 测试结果

方法二:没有封装的实体类

没有封装的实体类
结果用List<Map<Integer,String>>

/**  
 * 测试读2  
 * 没有分装的实体类用Map来存  
 */  
@Test  
void readExcel2() {  
    System.out.println("测试");  
    List<Map<Integer,String>> list = EasyExcel.read("D:\\测试\\demo.xlsx").sheet().doReadSync();  
    list.forEach(data ->{  
        String string = data.toString();  
        log.info("读取到数据{}",string);  
    });  
}
  • 测试结果同上

方法三:使用监听器来读取文件

使用监听器来读取文件

/**  
 * 测试读3  
 * 使用监听器读取文件。  
 * 需要我们额外创建一个监听器  
 */  
@Test  
void readExcel3() {  
    System.out.println("测试");  
    EasyExcel.read("D:\\测试\\demo.xlsx", DemoDate.class, new ExcelListener(demoService)).sheet().doRead();  
}
  • 这里需要额外写一个监听器
package com.nuc.demoexcel.listener;  
  
import com.alibaba.excel.context.AnalysisContext;  
import com.alibaba.excel.event.AnalysisEventListener;  
import com.alibaba.fastjson.JSON;  
import com.nuc.demoexcel.entity.DemoDate;  
import com.nuc.demoexcel.service.DemoService;  
import lombok.RequiredArgsConstructor;  
import lombok.extern.slf4j.Slf4j;  
  
import java.util.ArrayList;  
import java.util.List;  
  
/**  
 * 这里不能用SprongIoC容器来管理Listener,Listener可添加多个,会自动执行  
 */  
@Slf4j  
@RequiredArgsConstructor  
public class ExcelListener extends AnalysisEventListener<DemoDate> {  
  
    /**  
     * 每隔5条存储数据库,清理list,方便内存回收  
     */  
    private static final int BATCH_COUNT = 5;  
    private List<DemoDate> list = new ArrayList<DemoDate>();  
    private final DemoService demoService;  
  
    @Override  
    public void invoke(DemoDate demoDate, AnalysisContext analysisContext) {  
        log.info("读取到数据{}", JSON.toJSONString(demoDate));  
        list.add(demoDate);  
        // 到达批次数,保存数据,防止数据几万条数据在内存中,容易OOM  
        if (list.size() >= BATCH_COUNT) {  
            saveData();  
            // 保存完成,清理list  
            list.clear();  
        }  
  
    }  
  
  
    /**  
     * 所有的数据都读完,最后收尾数据  
     * @param analysisContext  
     */  
    @Override  
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {  
        //这里也要保存数据,确保最后遗留的数据也存储到数据库  
        saveData();  
        log.info("所有数据解析完成!");  
    }  
  
    /**  
     * 存储数据到数据库  
     */  
    private void saveData() {  
        log.info("{}条数据,开始存储数据库!", list.size());  
        demoService.saveData(list);  
        log.info("存储数据库成功!");  
    }  
}

这里只是演示EasyExcel
所以就不写Service层代码

4. Excel写入

  
/**  
 * 测试写  
 */  
@Test  
void testWrite() {  
    // 文件输出位置  
    String fileName = "D:\\text" + System.currentTimeMillis() + ".xlsx";  
    EasyExcel.write(fileName, DemoDate.class).sheet("模板").doWrite(data());  
  
  
  
}  
  
private List<DemoDate> data(){  
    //模拟数据  
    List<DemoDate> list = new ArrayList<>();  
    for (int i = 0; i < 13; i++) {  
        DemoDate data = new DemoDate();  
        data.setName("张三"+i);  
        data.setDate(new Date());  
        data.setDoubleData(Math.random()*100);  
        list.add(data);  
    }  
    return list;  
}
  • 成功写入

5. Excel下载&上传

package com.nuc.demoexcel.controller;  
  
import com.alibaba.excel.EasyExcel;  
import com.alibaba.fastjson.JSON;  
import com.nuc.demoexcel.entity.DemoDate;  
import com.nuc.demoexcel.listener.ExcelListener;  
import com.nuc.demoexcel.service.DemoService;  
import jakarta.servlet.http.HttpServletResponse;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.ResponseBody;  
import org.springframework.web.multipart.MultipartFile;  
  
import java.io.IOException;  
import java.net.URLEncoder;  
import java.util.*;  
  
@Controller  
public class UploadDownController {  
  
    @Autowired  
    private DemoService demoService;  
  
    /**  
     * 下载失败了(会返回一个有部分数据的Excel)  
     * @param response  
     * @throws IOException  
     */    @RequestMapping("/download")  
    public void download(HttpServletResponse  response) throws IOException {  
        response.setContentType("application/vnd.ms-excel");  
        response.setCharacterEncoding("utf-8");  
        //这里的encode是解决中文乱码, 这里必须使用UTF-8, 不然乱码  
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");  
        //这里使用附件的形式下载  
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");  
        EasyExcel.write(response.getOutputStream(), DemoDate.class).sheet("模板").doWrite(data());  
    }  
  
  
    @RequestMapping("/api/download")  
    public void downloadApi(HttpServletResponse response) throws IOException {  
        try {  
            response.setContentType("application/vnd.ms-excel");  
            response.setCharacterEncoding("utf-8");  
            //这里的encode是解决中文乱码, 这里必须使用UTF-8, 不然乱码  
            String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");  
            //这里使用附件的形式下载  
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");  
            EasyExcel.write(response.getOutputStream(), DemoDate.class).sheet("模板").doWrite(data());  
        } catch (IOException e) {  
            //重置响应  
            response.reset();  
            response.setContentType("application/json");  
            response.setCharacterEncoding("utf-8");  
            Map<String, Object> map = new HashMap<>();  
            map.put("status", 500);  
            map.put("message", "数据写入失败" + e.getMessage());  
            response.getWriter().println(JSON.toJSONString(map));  
        }  
  
    }  
  
    @PostMapping("/upload")  
    @ResponseBody  
    public String upload(MultipartFile file) throws IOException {  
        EasyExcel.read(file.getInputStream(), DemoDate.class, new ExcelListener(demoService)).sheet().doRead();  
        return "success";  
    }  
  
    private List<DemoDate> data(){  
        //模拟数据  
        List<DemoDate> list = new ArrayList<>();  
        for (int i = 0; i < 13; i++) {  
            DemoDate data = new DemoDate();  
            data.setName("张三"+i);  
            data.setDate(new Date());  
            data.setDoubleData(Math.random()*100);  
            list.add(data);  
        }  
        return list;  
    }  
}
  • 调用localhost:8080/download接口

5. Excel下载&上传

package com.nuc.demoexcel.controller;  
  
import com.alibaba.excel.EasyExcel;  
import com.alibaba.fastjson.JSON;  
import com.nuc.demoexcel.entity.DemoDate;  
import com.nuc.demoexcel.listener.ExcelListener;  
import com.nuc.demoexcel.service.DemoService;  
import jakarta.servlet.http.HttpServletResponse;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.ResponseBody;  
import org.springframework.web.multipart.MultipartFile;  
  
import java.io.IOException;  
import java.net.URLEncoder;  
import java.util.*;  
  
@Controller  
public class UploadDownController {  
  
    @Autowired  
    private DemoService demoService;  
  
    /**  
     * 下载失败了(会返回一个有部分数据的Excel)  
     * @param response  
     * @throws IOException  
     */    @RequestMapping("/download")  
    public void download(HttpServletResponse  response) throws IOException {  
        response.setContentType("application/vnd.ms-excel");  
        response.setCharacterEncoding("utf-8");  
        //这里的encode是解决中文乱码, 这里必须使用UTF-8, 不然乱码  
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");  
        //这里使用附件的形式下载  
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");  
        EasyExcel.write(response.getOutputStream(), DemoDate.class).sheet("模板").doWrite(data());  
    }  
  
  
    @RequestMapping("/api/download")  
    public void downloadApi(HttpServletResponse response) throws IOException {  
        try {  
            response.setContentType("application/vnd.ms-excel");  
            response.setCharacterEncoding("utf-8");  
            //这里的encode是解决中文乱码, 这里必须使用UTF-8, 不然乱码  
            String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");  
            //这里使用附件的形式下载  
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");  
            EasyExcel.write(response.getOutputStream(), DemoDate.class).sheet("模板").doWrite(data());  
        } catch (IOException e) {  
            //重置响应  
            response.reset();  
            response.setContentType("application/json");  
            response.setCharacterEncoding("utf-8");  
            Map<String, Object> map = new HashMap<>();  
            map.put("status", 500);  
            map.put("message", "数据写入失败" + e.getMessage());  
            response.getWriter().println(JSON.toJSONString(map));  
        }  
  
    }  
  
    @PostMapping("/upload")  
    @ResponseBody  
    public String upload(MultipartFile file) throws IOException {  
        EasyExcel.read(file.getInputStream(), DemoDate.class, new ExcelListener(demoService)).sheet().doRead();  
        return "success";  
    }  
  
    private List<DemoDate> data(){  
        //模拟数据  
        List<DemoDate> list = new ArrayList<>();  
        for (int i = 0; i < 13; i++) {  
            DemoDate data = new DemoDate();  
            data.setName("张三"+i);  
            data.setDate(new Date());  
            data.setDoubleData(Math.random()*100);  
            list.add(data);  
        }  
        return list;  
    }  
}
  • 调用localhost:8080/download接口

  • 调用localhost:8080/api/upload接口

  • 使用postman 调用localhost:8080/upload接口

    • 后端

总结 

到此这篇关于EasyExcel读写、模板填充、Web上传下载入门到实战的文章就介绍到这了,更多相关EasyExcel读写、模板填充、Web上传下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的构造方法this、super的用法详解

    Java中的构造方法this、super的用法详解

    这篇文章较详细的给大家介绍了Java中的构造方法this、super的用法,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-07-07
  • Java1.7全网最深入HashMap源码解析

    Java1.7全网最深入HashMap源码解析

    HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 nul
    2021-11-11
  • 对HashMap的数据结构的学习解读

    对HashMap的数据结构的学习解读

    这篇文章主要介绍了对HashMap的数据结构的学习心得,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • kafka并发写大消息异常TimeoutException排查记录

    kafka并发写大消息异常TimeoutException排查记录

    这篇文章主要为大家介绍了kafka并发写大消息异常TimeoutException的排查记录及解决方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • Hibernate初体验及简单错误排除代码详解

    Hibernate初体验及简单错误排除代码详解

    这篇文章主要介绍了Hibernate初体验及简单错误排除代码详解,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • 使用java为pdf添加书签的方法(pdf书签制作)

    使用java为pdf添加书签的方法(pdf书签制作)

    下载一些pdf格式的电子书没有书签,用JAVA写了一个小工具,将特定格式的文本解析成为书签,然后保存到pdf格式中
    2014-02-02
  • Java8的Optional如何干掉空指针(示例详解)

    Java8的Optional如何干掉空指针(示例详解)

    这篇文章主要介绍了Java8的Optional如何干掉空指针,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Idea springboot如何实现批量启动微服务

    Idea springboot如何实现批量启动微服务

    这篇文章主要介绍了Idea springboot如何实现批量启动微服务,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • springboot配置文件绑定实现解析

    springboot配置文件绑定实现解析

    这篇文章主要介绍了springboot配置文件绑定实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • springboot3.2整合mybatis-plus详细代码示例

    springboot3.2整合mybatis-plus详细代码示例

    这篇文章主要给大家介绍了关于springboot3.2整合mybatis-plus的相关资料,Spring Boot是一个非常流行的Java Web框架,可以快速地搭建Web应用程序,需要的朋友可以参考下
    2023-12-12

最新评论