记录一下自己用springboot整合阿里巴巴开源的EasyExcel实现导入导出功能
项目地址:https://github.com/changxueyi/springbootcrud
1.准备
项目的整体架构和图中的类似
2. 导入依赖
当然,基本的mysql-connector-java、mybaits、springboot的也需要导入,最重要的就是上面的
3、导出excel
dept实体类
导出 Excel 时,若需要表头,那么相应的实体类需要继承 BaseRowModel,并加入 @ExcelProperty(value = “id”, index = 0) 注解。其中 value 代表在导出 Excel 时,该字段对应的表头名称;index 代表该字段对应的表头位置(从0开始)。如下图:
1. 重要的代码
实体类对象
2. 控制层 DeptController
2.service业务层
3. 实现层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package com.cxy.service.Impl; import com.alibaba.excel.ExcelReader; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.support.ExcelTypeEnum; import com.cxy.common.poi.ExcelListener; import com.cxy.dao.DeptMapper; import com.cxy.domin.Dept; import com.cxy.service.DeptService; import org.apache.commons.lang3.RandomUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Random; /** * @ClassName DeptServiceImpl * @Description TODO * @Author changxueyi * @Date 2020/11/12 17:43 */ @Service public class DeptServiceImpl implements DeptService { @Autowired private DeptMapper deptMapper; @Override public void excelExport(HttpServletResponse response) throws IOException { List<Dept> list = deptMapper.queryAllDept(); String fileName = "用户名单" ; response.setContentType( "application/vnd.ms-excel;charset=utf-8" ); response.setCharacterEncoding( "utf-8" ); response.setHeader( "Content-disposition" , "attachment;filename=" + new String( fileName.getBytes( "gb2312" ), "ISO8859-1" ) + ".xls" ); ServletOutputStream out = response.getOutputStream(); ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLS, true ); Sheet sheet = new Sheet( 1 , 0 ,Dept. class ); //设置自适应宽度 sheet.setAutoWidth(Boolean.TRUE); sheet.setSheetName( "用户名单" ); writer.write(list,sheet); writer.finish(); out.flush(); response.getOutputStream().close(); out.close(); } @Override public void excelImport(MultipartFile file) throws IOException { if (!file.getOriginalFilename().equals( "用户名单.xls" ) && !file.getOriginalFilename().equals( "用户名单.xlsx" ) ){ return ; } InputStream inputStream = new BufferedInputStream(file.getInputStream()); //实例化实现了AnalysisEventListener接口的类 ExcelListener excelListener = new ExcelListener(deptMapper); ExcelReader reader = new ExcelReader(inputStream, null ,excelListener); //读取信息 reader.read( new Sheet( 1 , 1 ,Dept. class )); } } |
4.Mapper层
5.Mapper实现层
1 2 3 4 5 6 7 8 9 10 11 | <?xml version= "1.0" encoding= "UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace= "com.cxy.dao.DeptMapper" > <select id= "queryAllDept" resultType= "com.cxy.domin.Dept" > select * from dept </select> <insert id= "addDept" parameterType= "com.cxy.domin.Dept" > insert into dept values (#{deptNo},#{deptName},#{localtion}) </insert> </mapper> |
6.ExcelListener 工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | package com.cxy.common.poi; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.cxy.dao.DeptMapper; import com.cxy.domin.Dept; import org.springframework.stereotype.Controller; import java.util.ArrayList; import java.util.List; /** * @ClassName ExcelListener * @Description TODO * @Author changxueyi * @Date 2020/11/12 17:57 */ @Controller public class ExcelListener extends AnalysisEventListener<Dept> { private List<Dept> datas = new ArrayList<>(); private static final int BATCH_COUNT = 3000 ; private DeptMapper deptMapper; public ExcelListener(DeptMapper deptMapper){ this .deptMapper = deptMapper; } @Override public void invoke(Dept dept, AnalysisContext analysisContext) { //数据存储到datas,供批量处理,或后续自己业务逻辑处理。 datas.add(dept); //达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (datas.size() >= BATCH_COUNT){ saveData(); // 存储完成清理datas datas.clear(); } } private void saveData() { for (Dept dept : datas){ deptMapper.addDept(dept); } } public List<Dept> getDatas() { return datas; } public void setDatas(List<Dept> datas) { this .datas = datas; } /** * 所有数据解析完成了 都会来调用 */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { saveData(); //确保所有数据都能入库 } /* @Override public void invoke(Dept dept, AnalysisContext analysisContext) { }*/ } |
7. 导入的时候,文件名一定要固定
用户名单.xls
8.通过postMan使用的时候,需要注意以下几点
头部信息
9.导出功能
再用postman测试导出功能:#
没有参数,直接send,然后可以看到:
将其下载下来查看(本来这里的文件名应该是代码中命名的“用户名单.xls”,但我尝试了很久总是没有变。。。)
与数据库表数据一致,说明导出成功!
特别说明:
这里的excel名字的命名必须是这个,而且里面的主键可以不写,因为可能会遇到主键冲突的问题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?