SpringBoot实现Excel导入导出,好用到爆,POI可以扔掉了!

在我们平时工作中经常会遇到要操作Excel的功能,比如导出个用户信息或者订单信息的Excel报表。你肯定听说过POI这个东西,可以实现。但是POI实现的API确实很麻烦,它需要写那种逐行解析的代码(类似Xml解析)。今天给大家推荐一款非常好用的Excel导入导出工具EasyPoi,希望对大家有所帮助!

EasyPoi简介

用惯了SpringBoot的朋友估计会想到,有没有什么办法可以直接定义好需要导出的数据对象,然后添加几个注解,直接自动实现Excel导入导出功能?

EasyPoi正是这么一款工具,如果你不太熟悉POI,想简单地实现Excel操作,用它就对了!

EasyPoi的目标不是替代POI,而是让一个不懂导入导出的人也能快速使用POI完成Excel的各种操作,而不是看很多API才可以完成这样的工作。

集成

在SpringBoot中集成EasyPoi非常简单,只需添加如下一个依赖即可,真正的开箱即用!

<dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.4.0</version>
</dependency>

使用

接下来介绍下EasyPoi的使用,以会员信息和订单信息的导入导出为例,分别实现下简单的单表导出和具有关联信息的复杂导出。

简单导出

我们以会员信息列表导出为例,使用EasyPoi来实现下导出功能,看看是不是够简单!

  • 首先创建一个会员对象Member,封装会员信息;

/*** 购物会员* Created by macro on 2021/10/12.*/
@Data
@EqualsAndHashCode(callSuper = false)
public class Member {@Excel(name = "ID", width = 10)private Long id;@Excel(name = "用户名", width = 20, needMerge = true)private String username;private String password;@Excel(name = "昵称", width = 20, needMerge = true)private String nickname;@Excel(name = "出生日期", width = 20, format = "yyyy-MM-dd")private Date birthday;@Excel(name = "手机号", width = 20, needMerge = true, desensitizationRule = "3_4")private String phone;private String icon;@Excel(name = "性别", width = 10, replace = {"男_0", "女_1"})private Integer gender;
}
  • 在此我们就可以看到EasyPoi的核心注解@Excel,通过在对象上添加@Excel注解,可以将对象信息直接导出到Excel中去,下面对注解中的属性做个介绍;

    • name:Excel中的列名;

    • width:指定列的宽度;

    • needMerge:是否需要纵向合并单元格;

    • format:当属性为时间类型时,设置时间的导出导出格式;

    • desensitizationRule:数据脱敏处理,3_4表示只显示字符串的前3位和后4位,其他为*号;

    • replace:对属性进行替换;

    • suffix:对数据添加后缀。

  • 接下来我们在Controller中添加一个接口,用于导出会员列表到Excel,具体代码如下;

/*** EasyPoi导入导出测试Controller* Created by macro on 2021/10/12.*/
@Controller
@Api(tags = "EasyPoiController", description = "EasyPoi导入导出测试")
@RequestMapping("/easyPoi")
public class EasyPoiController {@ApiOperation(value = "导出会员列表Excel")@RequestMapping(value = "/exportMemberList", method = RequestMethod.GET)public void exportMemberList(ModelMap map,HttpServletRequest request,HttpServletResponse response) {List<Member> memberList = LocalJsonUtil.getListFromJson("json/members.json", Member.class);ExportParams params = new ExportParams("会员列表", "会员列表", ExcelType.XSSF);map.put(NormalExcelConstants.DATA_LIST, memberList);map.put(NormalExcelConstants.CLASS, Member.class);map.put(NormalExcelConstants.PARAMS, params);map.put(NormalExcelConstants.FILE_NAME, "memberList");PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);}
}
  • LocalJsonUtil工具类,可以直接从resources目录下获取JSON数据并转化为对象,例如此处使用的members.json

695a6d541461933feb88a946a6dfe04c.png
  • 运行项目,直接通过Swagger访问接口,注意在Swagger中访问接口无法直接下载,需要点击返回结果中的下载按钮才行,访问地址:http://localhost:8088/swagger-ui/

456ff7d89081fb0fa344b2f3e56a1002.png
  • 下载完成后,查看下文件,一个标准的Excel文件已经被导出了。

b7acbde7f24cdae224db61eb37973e73.png

简单导入

导入功能实现起来也非常简单,下面以会员信息列表的导入为例。

  • 在Controller中添加会员信息导入的接口,这里需要注意的是使用@RequestPart注解修饰文件上传参数,否则在Swagger中就没法显示上传按钮了;

/*** EasyPoi导入导出测试Controller* Created by macro on 2021/10/12.*/
@Controller
@Api(tags = "EasyPoiController", description = "EasyPoi导入导出测试")
@RequestMapping("/easyPoi")
public class EasyPoiController {@ApiOperation("从Excel导入会员列表")@RequestMapping(value = "/importMemberList", method = RequestMethod.POST)@ResponseBodypublic CommonResult importMemberList(@RequestPart("file") MultipartFile file) {ImportParams params = new ImportParams();params.setTitleRows(1);params.setHeadRows(1);try {List<Member> list = ExcelImportUtil.importExcel(file.getInputStream(),Member.class, params);return CommonResult.success(list);} catch (Exception e) {e.printStackTrace();return CommonResult.failed("导入失败!");}}
}
  • 然后在Swagger中测试接口,选择之前导出的Excel文件即可,导入成功后会返回解析到的数据。

8f6640bb78b3e0576c6e400f1d61ba06.png

复杂导出

当然EasyPoi也可以实现更加复杂的Excel操作,比如导出一个嵌套了会员信息和商品信息的订单列表,下面我们来实现下!

  • 首先添加商品对象Product,用于封装商品信息;

/*** 商品* Created by macro on 2021/10/12.*/
@Data
@EqualsAndHashCode(callSuper = false)
public class Product {@Excel(name = "ID", width = 10)private Long id;@Excel(name = "商品SN", width = 20)private String productSn;@Excel(name = "商品名称", width = 20)private String name;@Excel(name = "商品副标题", width = 30)private String subTitle;@Excel(name = "品牌名称", width = 20)private String brandName;@Excel(name = "商品价格", width = 10)private BigDecimal price;@Excel(name = "购买数量", width = 10, suffix = "件")private Integer count;
}
  • 然后添加订单对象Order,订单和会员是一对一关系,使用@ExcelEntity注解表示,订单和商品是一对多关系,使用@ExcelCollection注解表示,Order就是我们需要导出的嵌套订单数据;

/*** 订单* Created by macro on 2021/10/12.*/
@Data
@EqualsAndHashCode(callSuper = false)
public class Order {@Excel(name = "ID", width = 10,needMerge = true)private Long id;@Excel(name = "订单号", width = 20,needMerge = true)private String orderSn;@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss",needMerge = true)private Date createTime;@Excel(name = "收货地址", width = 20,needMerge = true )private String receiverAddress;@ExcelEntity(name = "会员信息")private Member member;@ExcelCollection(name = "商品列表")private List<Product> productList;
}
  • 接下来在Controller中添加导出订单列表的接口,由于有些会员信息我们不需要导出,可以调用ExportParams中的setExclusions方法排除掉;

/*** EasyPoi导入导出测试Controller* Created by macro on 2021/10/12.*/
@Controller
@Api(tags = "EasyPoiController", description = "EasyPoi导入导出测试")
@RequestMapping("/easyPoi")
public class EasyPoiController {@ApiOperation(value = "导出订单列表Excel")@RequestMapping(value = "/exportOrderList", method = RequestMethod.GET)public void exportOrderList(ModelMap map,HttpServletRequest request,HttpServletResponse response) {List<Order> orderList = getOrderList();ExportParams params = new ExportParams("订单列表", "订单列表", ExcelType.XSSF);//导出时排除一些字段params.setExclusions(new String[]{"ID", "出生日期", "性别"});map.put(NormalExcelConstants.DATA_LIST, orderList);map.put(NormalExcelConstants.CLASS, Order.class);map.put(NormalExcelConstants.PARAMS, params);map.put(NormalExcelConstants.FILE_NAME, "orderList");PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);}
}
  • 在Swagger中访问接口测试,导出订单列表对应Excel;

b9c0b50ac6c8bc2a7df7536065c7519b.png
  • 下载完成后,查看下文件,EasyPoi导出复杂的Excel也是很简单的!

c8f28e9f657e5195bc953a268cde9b56.png

自定义处理

如果你想对导出字段进行一些自定义处理,EasyPoi也是支持的,比如在会员信息中,如果用户没有设置昵称,我们添加下暂未设置信息。

  • 我们需要添加一个处理器继承默认的ExcelDataHandlerDefaultImpl类,然后在exportHandler方法中实现自定义处理逻辑;

/*** 自定义字段处理* Created by macro on 2021/10/13.*/
public class MemberExcelDataHandler extends ExcelDataHandlerDefaultImpl<Member> {@Overridepublic Object exportHandler(Member obj, String name, Object value) {if("昵称".equals(name)){String emptyValue = "暂未设置";if(value==null){return super.exportHandler(obj,name,emptyValue);}if(value instanceof String&&StrUtil.isBlank((String) value)){return super.exportHandler(obj,name,emptyValue);}}return super.exportHandler(obj, name, value);}@Overridepublic Object importHandler(Member obj, String name, Object value) {return super.importHandler(obj, name, value);}
}
  • 然后修改Controller中的接口,调用MemberExcelDataHandler处理器的setNeedHandlerFields设置需要自定义处理的字段,并调用ExportParamssetDataHandler设置自定义处理器;

/*** EasyPoi导入导出测试Controller* Created by macro on 2021/10/12.*/
@Controller
@Api(tags = "EasyPoiController", description = "EasyPoi导入导出测试")
@RequestMapping("/easyPoi")
public class EasyPoiController {@ApiOperation(value = "导出会员列表Excel")@RequestMapping(value = "/exportMemberList", method = RequestMethod.GET)public void exportMemberList(ModelMap map,HttpServletRequest request,HttpServletResponse response) {List<Member> memberList = LocalJsonUtil.getListFromJson("json/members.json", Member.class);ExportParams params = new ExportParams("会员列表", "会员列表", ExcelType.XSSF);//对导出结果进行自定义处理MemberExcelDataHandler handler = new MemberExcelDataHandler();handler.setNeedHandlerFields(new String[]{"昵称"});params.setDataHandler(handler);map.put(NormalExcelConstants.DATA_LIST, memberList);map.put(NormalExcelConstants.CLASS, Member.class);map.put(NormalExcelConstants.PARAMS, params);map.put(NormalExcelConstants.FILE_NAME, "memberList");PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);}
}
  • 再次调用导出接口,我们可以发现昵称已经添加默认设置了。

3f8a4f5d59ed2fc67ebc588fa60cde7d.png

总结

体验了一波EasyPoi,它使用注解来操作Excel的方式确实非常好用。如果你想生成更为复杂的Excel的话,可以考虑下它的模板功能。

参考资料

项目官网:https://gitee.com/lemur/easypoi

21e6f9e123bb2f310ebf3d2f087bd0ec.gif

往期推荐

c949e58c91aa825978ba39229818c3a4.png

再见 Postman!Apifox 才是 YYDS!


91c298d8f5e2a179095fd8ffadb16046.png

再见收费的Navicat!操作所有数据库靠它就够了!


da58c5877d807f2554e975ef470a3d0e.png

MyBatis原生批量插入的坑与解决方案!



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544528.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python datetime __str __()方法与示例

Python datetime .__ str __()方法 (Python datetime.__str__() Method) datetime.__str__() method is used to manipulate objects of datetime class of module datetime. datetime .__ str __()方法用于操作模块datetime的datetime类的对象。 It uses a datetime class o…

Facebook升级到MySQL 8.0付出的代价

近日&#xff0c;Facebook 官博公布了他们的数据库版本从 MySQL 5.6 升级到了 MySQL 8.0&#xff0c;并且在官博记录了复盘详细的升级过程。Facebook 称&#xff0c;他们最近的一次大版本升级到 MySQL 5.6 花了一年多时间才完成&#xff0c;还在 5.6 版上开发 LSM 树存储引擎&a…

Matlab制作朱利表

朱利判据 其中 {bn−kan−k−ana0∗akcn−kbn−k−bnb0∗bk...qn−kpn−k−pnp0∗pk\begin{cases} b_{n-k}a_{n-k}-\frac{a_n}{a_0}*a_k\\ c_{n-k}b_{n-k}-\frac{b_n}{b_0}*b_k\\ ...\\ q_{n-k}p_{n-k}-\frac{p_n}{p_0}*p_k \end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧​bn−k​an−k​−a0…

HDOJ 1047 Integer Inquiry

JAVA睑板.... Integer Inquiry Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12042 Accepted Submission(s): 3037Problem DescriptionOne of the first users of BITs new supercomputer was Chip Diller. …

高并发下秒杀商品,必须知道的9个细节

高并发下如何设计秒杀系统&#xff1f;这是一个高频面试题。这个问题看似简单&#xff0c;但是里面的水很深&#xff0c;它考查的是高并发场景下&#xff0c;从前端到后端多方面的知识。秒杀一般出现在商城的促销活动中&#xff0c;指定了一定数量&#xff08;比如&#xff1a;…

weakhashmap_Java WeakHashMap keySet()方法与示例

weakhashmapWeakHashMap类的keySet()方法 (WeakHashMap Class keySet() method) keySet() method is available in java.util package. keySet()方法在java.util包中可用。 keySet() method is used to retrieve all the key exists in this map to be viewed in a set. keySet…

最小拍控制系统详细解读(阶跃输入+速度输入2个案例)【Simulink仿真】

目录索引1.符号说明与结构框图2.最小拍控制系统构造原则2.1数字控制器D(z)的构造3.简单控制对象的最小拍控制器设计3.1阶跃输入3.2速度输入1.符号说明与结构框图 y(k)——系统响应输出的离散值u(k)——数字PID控制输出的离散值r(k)——期望输出的离散值&#xff08;事先已知&a…

php中重写和final关键字的使用

为什么把重写和final放在一起&#xff0c;原因就是一条&#xff1a;final的意思是不可更改的&#xff0c;也就是说final定义的东西是不可改变的&#xff0c;下面具体来说一下。 来看一段简单的代码&#xff1a; 1 class BaseClass {2 final public function test() {3 …

java vector_Java Vector lastElement()方法与示例

java vector向量类的lastElement()方法 (Vector Class lastElement() method) lastElement() method is available in java.util package. lastElement()方法在java.util包中可用。 lastElement() method is used to return the last element of this Vector. lastElement()方法…

SpringBoot官方热部署和远程调试神器,真带劲!

平时使用SpringBoot开发应用时&#xff0c;修改代码后需要重新启动才能生效。如果你的应用足够大的话&#xff0c;启动可能需要好几分钟。有没有什么办法可以加速启动过程&#xff0c;让我们开发应用代码更高效呢&#xff1f;今天给大家推荐一款SpringBoot官方的热部署工具spri…

【Python】输入任意个数元素并保存至列表

目录1.导入任意个数元素到列表1.1.编程思路1.2.代码片2.查找一个重复元素在列表中的所有位置2.1.编程思路2.2代码片1.导入任意个数元素到列表 1.1.编程思路 输入未知个数的元素需要用列表来存储&#xff0c;由于Python具有内存的动态分配能力&#xff0c;列表不需要手动动态分…

MySQL 性能优化的 9 种姿势,面试再也不怕了!

大家好&#xff0c;我是磊哥&#xff01;今天给大家分享一些简单好用的数据库优化方式&#xff01;1、选择最合适的字段属性Mysql是一种关系型数据库&#xff0c;可以很好地支持大数据量的存储&#xff0c;但是一般来说&#xff0c;数据库中的表越小&#xff0c;在它上面执行的…

containsall_Java Vector containsAll()方法与示例

containsall向量类containsAll()方法 (Vector Class containsAll() method) containsAll() method is available in java.util package. containsAll()方法在java.util包中可用。 containsAll() method is used to test the existence of all the elements of this Vector in t…

Excel的规划求解【详细步骤】

本文目录1.说明2.准备加载项步骤1步骤2步骤33.线性规划问题步骤4步骤5步骤61.说明 使用Lingo程序也可以实现线性规划、非线性规划以及0-1规划&#xff0c;但是在缺少Lingo程序的情况下&#xff0c;我们使用Excel照样可以很容易地完成。在这里我给大家提供了解决此类问题的详细…

4 种方法!检查字符串是否为合法的日期格式

哈喽大家好&#xff0c;今天咱们来讲一下&#xff0c;Java 中如何检查一个字符串是否是合法的日期格式&#xff1f;为什么要检查时间格式&#xff1f;后端接口在接收数据的时候&#xff0c;都需要进行检查。检查全部通过后&#xff0c;才能够执行业务逻辑。对于时间格式&#x…

linux下tomcat无法显示图片验证码

在catalina.sh中的-Djava.io.tmpdir"$CATALINA_TMPDIR" \后一行增加 -Djava.awt.headlesstrue \ 共8处转载于:https://blog.51cto.com/zhangfeikr/1673312

Java Throwable toString()方法与示例

Throwable类toString()方法 (Throwable Class toString() method) toString() Method is available in java.lang package. toString()方法在java.lang包中可用。 toString() Method is used to return a short description of the exception. toString()方法用于返回对该异常的…

【Matlab】根据图生成带权邻接矩阵,并求出最短路径

目录图的简介无向图&#xff08;Graph&#xff09;生成带权邻接矩阵求两点最短路径有向图&#xff08;Digraph&#xff09;生成带权邻接矩阵求最短路径图的简介 图是拓扑学中的一个重要概念&#xff0c;分为无向图和有向图两种。图有两个重要属性&#xff0c;即点&#xff08;…

阿里二面:为什么要分库分表?

在高并发系统当中&#xff0c;分库分表是必不可少的技术手段之一&#xff0c;同时也是BAT等大厂面试时&#xff0c;经常考的热门考题。你知道我们为什么要做分库分表吗&#xff1f;这个问题要从两条线说起&#xff1a;垂直方向 和 水平方向。1 垂直方向垂直方向主要针对的是业务…

java scanner_Java Scanner nextDouble()方法与示例

java scanner扫描仪类的nextDouble()方法 (Scanner Class nextDouble() method) nextDouble() method is available in java.util package. nextDouble()方法在java.util包中可用。 nextDouble() method is used to scans the next token of the input scanned into a double v…