2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Springboot 整合 easyexcel导入导出excel

Springboot 整合 easyexcel导入导出excel

时间:2021-06-10 03:31:26

相关推荐

Springboot 整合 easyexcel导入导出excel

1. 引入核心依赖

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>28.2-jre</version></dependency>

只有easyexcel 是必须的

1. 根据实体类导出

@Datapublic class Student {@ExcelProperty("姓名")private String name;@ExcelProperty("年龄")private Integer age;@ExcelProperty("成绩")private BigDecimal score;}

ExcelProperty代表导出列表头

来看看 Controller

// 模拟从数据库查询出来的数据private List<Student> data() {List<Student> list = new ArrayList<Student>();for (int i = 0; i < 10; i++) {Student student = new Student();list.add(student);student.setName("张三" + i);student.setAge(18 + i);student.setScore(new BigDecimal(i + ""));}return list;}// 导出@GetMapping("download")public void download(HttpServletResponse response) throws IOException {// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");// Student.class 是按导出类 data()应为数据库查询数据,这里只是模拟EasyExcel.write(response.getOutputStream(), Student.class).sheet("模板").doWrite(data());}

这里导出就写完了,我们直接调用 http://localhost:8081/download 来看看效果

是不是特别轻松简单

2. 读取数据

读取数据是一行一行读取的,所以需要创建一个读取一行数据后的监听器

这个监听器需要继承AnalysisEventListener类,大致代码如下

StudentListener

package com..Listener;import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.event.AnalysisEventListener;import com.alibaba.fastjson.JSON;import com..Dao.StudentDao;import com..model.Student;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.ArrayList;import java.util.List;/*** @author WH* @version 1.0* @date /4/18 20:56* @Description TODO*/public class StudentListener extends AnalysisEventListener<Student> {private static final Logger LOGGER =LoggerFactory.getLogger(com..Listener.StudentListener.class);/*** 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;List<Student> list = new ArrayList<Student>();/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private StudentDao studentDao;/*** 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来** @param studentDao*/public StudentListener(StudentDao studentDao) {this.studentDao = studentDao;}/*** 这个每一条数据解析都会来调用** @param student* one row value. Is is same as {@link AnalysisContext#readRowHolder()}* @param analysisContext*/@Overridepublic void invoke(Student student, AnalysisContext analysisContext) {System.out.println("invoke方法被调用");LOGGER.info("解析到一条数据:{}", JSON.toJSONString(student));list.add(student);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {System.out.println("doAfterAllAnalysed方法 被调用");// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();LOGGER.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {LOGGER.info("{}条数据,开始存储数据库!", list.size());studentDao.save(list);LOGGER.info("存储数据库成功!");}}

controller层

/*** 读取 excel* @return*/@PostMapping("upload")@ResponseBodypublic String upload(MultipartFile file) throws IOException {//写法一// sheet里面可以传参 根据sheet下标读取或者根据名字读取 不传默认读取第一个EasyExcel.read(file.getInputStream(), Student.class, new StudentListener(studentDao)).sheet().doRead();.// 写法2:/*ExcelReader excelReader = EasyExcel.read(file.getInputStream(), Student.class, new StudentListener(studentDao)).build();ReadSheet readSheet = EasyExcel.readSheet(0).build();excelReader.read(readSheet);// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的excelReader.finish();*/return "success";}

读取excel是如何匹配的,这里我们传入的还是原来的 Student.class

会根据@ExcelProperty 名字去匹配,如果名字重复,会导致只有一个字段读取到数据

也可以通过index 去匹配类似这样

/**

* 强制读取第三个 不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配

*/

@ExcelProperty(index = 2)

实现效果大致是这样

填充excel

有时候我们用传统的excel导出一些报表按一些特定的格式,拼接表头是最恶心的地方,这里我们可以通过配置模板导出

这里我们以填充集合为例

假定要填充 list结合 ,集合Student属性有两个 name ,age

我们先选择一个模板excel放入项目中

然后将数据填充到这个模板中导出,这里以常用的填充list集合为例

固定格式中name 和number需要替换为你自己实体类的属性

测试案例

@GetMapping("template")public String downloadDataByExcelTemplate(HttpServletResponse response) throws Exception {// 获取模板路径/** public static String getPath() { return TestFileUtil.class.getResource("/").getPath(); }**/String templateFileName =TestFileUtil.getPath() + "excel" + File.separator + "list.xlsx";System.out.println("templateFileName" +templateFileName);response.setContentType("application/vnd.ms-excel");String fileName = TestFileUtil.getPath() + "listFill" + System.currentTimeMillis() + ".xlsx";response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");System.out.println("fileName" + fileName);EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet().doFill(data());return "success";}

w我模板锁放的位置:

模板:

直接调用这个接口测试

更多教程

更多教程请参考官网

github

源码下载

/weihubeats/springcloud-shopping-parent.git

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。