SpringBoot+EasyPoi实现excel导出功能
作者:12程序猿 发布时间:2022-05-08 06:47:35
在实际项目开发中,对于Excel的导入导出还是很常见的需求,比如说将数据根据模板批量导入到数据库中,以及将数据库中的数据批量导出陈Excel的形式
现有需求: 根据检索条件查询列表并将结果导出到excel
Easypoi文档:https://easypoi.mydoc.io/#text_186900
EasyPoi的主要特点
1.设计精巧,使用简单
2.接口丰富,扩展简单
3.默认值多,write less do more
4.spring mvc支持,web导出可以简单明了
实现过程
1.创建一个Spring Boot项目
快速生成链接:start.spring.io
2.引入EasyPoi的pom依赖
<!--EasyPoi导入导出-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.3.0</version>
</dependency>
easypoi-base 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能
easypoi-web 耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能
easypoi-annotation 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理
sax 导入使用xercesImpl这个包(这个包可能造成奇怪的问题哈),word导出使用poi-scratchpad,都作为可选包了
pom.xml中的所有依赖:
<dependencies>
<!-- 导入web支持:SpringMVC开发支持,Servlet相关的程序 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatis相关的依赖 -->
<!--mybatis-plus自动的维护了mybatis以及mybatis-spring的依赖,
在springboot中这三者不能同时的出现,避免版本的冲突,表示:跳进过这个坑-->
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
<!--swagger2依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<!--排除自身的依赖1.5.20版本-->
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--此版本解决 example="" 造成的 空字符串""无法转成Number 问题-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
<!--EasyPoi导入导出-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.3.0</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.71</version>
</dependency>
</dependencies>
3.编写excel工具类
package com.example.easypoiexceldemo.utils;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* excel工具类
* @author qzz
*/
public class ExcelUtils {
/**
* Excel导出
*
* @param response response
* @param fileName 文件名
* @param list 数据List
* @param pojoClass 对象Class
*/
public static void exportExcel(HttpServletResponse response, String fileName, Collection<?> list, Class<?> pojoClass) throws IOException {
if (StringUtils.isBlank(fileName)) {
//当前日期
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
fileName = df.format(new Date());
}
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(fileName, fileName, ExcelType.HSSF), pojoClass, list);
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls");
ServletOutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
}
/**
* Excel导出,先sourceList转换成List<targetClass>,再导出
*
* @param response response
* @param fileName 文件名
* @param sourceList 原数据List
* @param targetClass 目标对象Class
*/
public static void exportExcelToTarget(HttpServletResponse response, String fileName, Collection<?> sourceList, Class<?> targetClass) throws Exception {
List targetList = new ArrayList<>(sourceList.size());
for (Object source : sourceList) {
Object target = targetClass.newInstance();
BeanUtils.copyProperties(source, target);
targetList.add(target);
}
exportExcel(response, fileName, targetList, targetClass);
}
/**
* Excel导出----设置title---sheetName---要求Collection<?> list是Class<?> pojoClass类型的
*
* @param response response
* @param fileName 文件名
* @param list 数据List
* @param pojoClass 对象Class
*/
public static void exportExcel(HttpServletResponse response, String title, String sheetName, String fileName, Collection<?> list, Class<?> pojoClass) throws IOException {
if (StringUtils.isBlank(fileName)) {
//当前日期
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
fileName = df.format(new Date());
}
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(title, sheetName, ExcelType.HSSF), pojoClass, list);
response.setCharacterEncoding("UTF-8");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xls");
ServletOutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
}
}
4.在实体类上加注解@Excel
我这边使用了lombok。getter setter和构造方法通过注解 @Data @AllArgsConstructor进行添加,不使用lombok也可手动添加。
要导出的数据可在实体类对应属性上方加**@Excel()注解
**。可定义导出列的名称、宽度,以及性别可区分化(一般数据库中存储的性别为1和2),日期格式化等等。
package com.example.easypoiexceldemo.excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.util.Date;
/**
* 商品
* @author qzz
*/
@Data
public class ProductExcel {
/**
* 商品id
*/
@Excel(name = "商品id")
private Integer product_id;
/**
* 商品标题
*/
@Excel(name="商品标题")
private String title;
/**
* 商品副标题
*/
@Excel(name="商品副标题")
private String sub_title;
/**
* 商品售价
*/
@Excel(name="商品售价")
private Double sale_price;
/**
* 创建者
*/
@Excel(name="创建者")
private Integer create_by;
/**
* 创建时间
*/
@Excel(name="创建时间", format = "yyyy-MM-dd")
private Date create_time;
/**
* 修改时间
*/
@Excel(name="修改时间", format = "yyyy-MM-dd")
private Date update_time;
/**
* 修改者id
*/
@Excel(name="修改者id")
private Integer update_by;
}
@Excel 作用到filed上面,是对Excel一列的一个描述
@Excel 的属性介绍:
5.Controller
/**
* excel导出
* @param response
*/
@GetMapping("/excel")
@ApiOperation("根据检索条件查询列表,导出excel")
public void export( HttpServletResponse response) throws IOException {
//根据条件检索列表
QueryWrapper<Product> queryWrapper = new QueryWrapper();
//根据条件检索商品列表
List<Map<String, Object>> list = productService.selectList(queryWrapper);
//将List<Map<String, Object>>结果集转换成List<ProductExcel>
List<ProductExcel> productList = MapToEntity.setList(list,ProductExcel.class);
//导出excel
ExcelUtils.exportExcel(response,null,productList, ProductExcel.class);
}
setList方法为工具类,用于将List<Map<String, Object>>结果集转换成List
MapToEntity工具类:
package com.example.easypoiexceldemo.utils;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* List<Map<String,Object>>到List<T>数据转换
* @author qzz
*/
public class MapToEntity {
/**
* List<Map<String, Object>> 到 List<T> 数据转换
*/
public static <T> List<T> setList(final List<Map<String, Object>> srcList, Class<T> clazz) {
List<T> list = new ArrayList<>();
for (int i=0;i<srcList.size();i++){
try {
T t = clazz.newInstance();
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
if (!"serialVersionUID".equals(field.getName())) {
//设置对象的访问权限,保证对private的属性的访问
field.setAccessible(true);
//读取配置转换字段名,并从map中取出数据
Object v = srcList.get(i).get(field.getName());
field.set(t, convert(v, field.getType()));
}
}
list.add(t);
} catch (Exception ex) {
ex.toString();
}
};
return list;
}
/**
* 字段类型转换
*/
private static <T> T convert(Object obj, Class<T> type) throws ParseException {
if (obj != null && StringUtils.isNotBlank(obj.toString())) {
if (type.equals(String.class)) {
return (T) obj.toString();
} else if (type.equals(BigDecimal.class)) {
return (T) new BigDecimal(obj.toString());
}else if(type.equals(Double.class)){
return (T) Double.valueOf(obj.toString());
}else if(type.equals(Integer.class)){
return (T) Integer.valueOf(obj.toString());
}else if(type.equals(Date.class)){
if(obj!=null){
String timeStr = String.valueOf(obj);
String s[] = timeStr.split("T");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return (T) sdf.parse(s[0]+" "+s[1]);
}else{
return null;
}
}
else{
//其他类型转换
return (T) obj.toString();
}
}
return null;
}
}
6.启动项目,进行测试
项目启动成功后,在浏览器中输入 http://localhost:8083/product/excel,进行访问:
打开导出的excel文档:
来源:https://blog.csdn.net/qq_26383975/article/details/120139457


猜你喜欢
- Java类成员变量的默认值基本数据类型作为类的成员变量时可以不赋予初值,在方法中输出也不会报错。下面我们看看我们的八种数据类型的默认值是什么
- 前言Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了“伪泛型”的策略,即Java在语法上
- Android 获取IP地址最近做项目,有一个需求是Android设备获取当前IP的功能,经过一番查询资料解决了,记录下实现方法。1.使用W
- InputStream转化为base64项目经常会用到将文件转化为base64进行传输怎么才能将文件流转化为base64呢,代码如下/**
- 本文实例为大家分享了Android读取手机通讯录联系人到项目的具体代码,供大家参考,具体内容如下一、主界面代码如下:<LinearLa
- 快速排序算法概念快速排序一般基于递归实现。其思路是这样的:1.选定一个合适的值(理想情况中值最好,但实现中一般使用数组第一个值),称为“枢轴
- 我们经常看到使用了ViewPager的App,在每页上面都会有一个滑块来标志当前处于哪一页。在PagerView包里有android.sup
- 使用lombok插件的好处我们在java开发过程中,经常会有一些常规性的,重复性的工作。比如:根据成员变量生成get和set方法根据成员变量
- 先明确几个概念的区别: padding margin都是边距的含义,关键问题得明白是什么相对什么的边距. padding是控件的内容相对控件
- Java * 。具体有如下四步骤:通过实现 InvocationHandler 接口创建自己的调用处理器;通过为 Proxy 类指定 C
- 本文实例讲述了C#.net实现在Winform中从internet下载文件的方法。分享给大家供大家参考。具体如下:自己做了一个通用的软件自动
- 需要5个类:1.实体类:Person.java2.抽象类:SQLOperate.java(封装了对数据库的操作)3.助手类:DBOpenHe
- 今天在优化项目中的考勤同步功能时遇到将考勤机中的数据同步到数据库,两边都是几万条数据的样子,老代码的做法差不多半个小时,优化后我本机差不多4
- 前 言最近和我们老大一起做技术面试(我是旁听的),发现前来面试的没几个掌握甚至是丁点了解LINQ。这让我很纳闷,LINQ伴随2008一起发布
- 接收JSON浏览器传来的参数,可以是 key/value 形式的,也可以是一个 JSON 字符串。在 Jsp/Servlet 中,我们接收
- 本文实例为大家分享了Android Studio实现简易进制转换计算器的具体代码,供大家参考,具体内容如下1、问题描述设计并实现一个数制转换
- 在我的工作经验中,在C#语言本身的学习上花了大量的时间,积累了一些经验,一些是在学习和工作中遇到的问题和解决办法分享出来,希望大家也能有收获
- 今天学习了Mybatis执行存储,感觉不是那么好用,可能是我没用习惯。我先在SQLSERVER创建存储alter procedure usp
- 代码如下:try { // 创建一个线程 Thread thread = new Thread() {
- 本文实例为大家分享了Android实现时钟特效的具体代码,供大家参考,具体内容如下效果展示:功能介绍:如果您想换一张背景图,可以点击左下角按