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上传下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mac下eclipse项目根目录没有.setting文件夹的解决方案

    Mac下eclipse项目根目录没有.setting文件夹的解决方案

    文章介绍了如何通过修改项目根路径下.setting文件夹中的org.eclipse.wst.common.project.facet.core.xml文件来解决Web版本问题
    2026-02-02
  • Redisson分布式锁实现原理示例详解

    Redisson分布式锁实现原理示例详解

    Redisson分布式锁通过Lua脚本保证原子性操作,实现了分布式互斥、可重入、自动续期等核心特性,其高级特性包括公平锁、读写锁和红锁算法,能够满足不同场景下的并发控制需求,这篇文章主要介绍了Redisson分布式锁实现原理的相关资料,需要的朋友可以参考下
    2026-04-04
  • 用java实现学生信息管理系统

    用java实现学生信息管理系统

    这篇文章主要为大家详细介绍了java实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • java实战之桌球小游戏

    java实战之桌球小游戏

    这篇文章主要为大家详细介绍了java实战之桌球小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • 详解Java如何优雅的实现异常捕获

    详解Java如何优雅的实现异常捕获

    在一个优秀的项目中一定少不了对程序流程良好的异常捕获与日志打印,所以本文主要为大家介绍了如何优雅的实现异常捕获与日志打印输出,有需要的可以参考下
    2023-09-09
  • 开源项目ERM模型转jpa实体maven插件使用

    开源项目ERM模型转jpa实体maven插件使用

    这篇文章主要为大家介绍了开源项目ERM模型转jpa实体maven插件的使用说明,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • SpringCloud Zuul过滤器实现登陆鉴权代码实例

    SpringCloud Zuul过滤器实现登陆鉴权代码实例

    这篇文章主要介绍了SpringCloud Zuul过滤器实现登陆鉴权代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • java 数据的加密与解密普遍实例代码

    java 数据的加密与解密普遍实例代码

    本篇文章介绍了一个关于密钥查询的jsp文件简单实例代码,需要的朋友可以参考下
    2017-04-04
  • 一种类似JAVA线程池的C++线程池实现方法

    一种类似JAVA线程池的C++线程池实现方法

    线程池(thread pool)是一种线程使用模式。线程过多或者频繁创建和销毁线程会带来调度开销,进而影响缓存局部性和整体性能。这篇文章主要介绍了一种类似JAVA线程池的C++线程池实现方法,需要的朋友可以参考下
    2019-07-07
  • 使用@RequestParam设置默认可以传空值

    使用@RequestParam设置默认可以传空值

    这篇文章主要介绍了使用@RequestParam设置默认可以传空值的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论