SpringBoot+EasyPoi實(shí)現(xiàn)excel導(dǎo)出功能
在實(shí)際項(xiàng)目開發(fā)中,對(duì)于Excel的導(dǎo)入導(dǎo)出還是很常見(jiàn)的需求,比如說(shuō)將數(shù)據(jù)根據(jù)模板批量導(dǎo)入到數(shù)據(jù)庫(kù)中,以及將數(shù)據(jù)庫(kù)中的數(shù)據(jù)批量導(dǎo)出陳Excel的形式
現(xiàn)有需求: 根據(jù)檢索條件查詢列表并將結(jié)果導(dǎo)出到excel
Easypoi文檔:https://easypoi.mydoc.io/#text_186900
EasyPoi的主要特點(diǎn)
1.設(shè)計(jì)精巧,使用簡(jiǎn)單
2.接口豐富,擴(kuò)展簡(jiǎn)單
3.默認(rèn)值多,write less do more
4.spring mvc支持,web導(dǎo)出可以簡(jiǎn)單明了
實(shí)現(xiàn)過(guò)程
1.創(chuàng)建一個(gè)Spring Boot項(xiàng)目
快速生成鏈接:start.spring.io

2.引入EasyPoi的pom依賴
<!--EasyPoi導(dǎo)入導(dǎo)出--> <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 導(dǎo)入導(dǎo)出的工具包,可以完成Excel導(dǎo)出,導(dǎo)入,Word的導(dǎo)出,Excel的導(dǎo)出功能
- easypoi-web 耦合了spring-mvc 基于AbstractView,極大的簡(jiǎn)化spring-mvc下的導(dǎo)出功能
- easypoi-annotation 基礎(chǔ)注解包,作用與實(shí)體對(duì)象上,拆分后方便maven多工程的依賴管理
sax 導(dǎo)入使用xercesImpl這個(gè)包(這個(gè)包可能造成奇怪的問(wèn)題哈),word導(dǎo)出使用poi-scratchpad,都作為可選包了
pom.xml中的所有依賴:
<dependencies>
<!-- 導(dǎo)入web支持:SpringMVC開發(fā)支持,Servlet相關(guān)的程序 -->
<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相關(guān)的依賴 -->
<!--mybatis-plus自動(dòng)的維護(hù)了mybatis以及mybatis-spring的依賴,
在springboot中這三者不能同時(shí)的出現(xiàn),避免版本的沖突,表示:跳進(jìn)過(guò)這個(gè)坑-->
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<!--mysql驅(qū)動(dòng)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- alibaba的druid數(shù)據(jù)庫(kù)連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.20</version>
</dependency>
<!-- alibaba的druid數(shù)據(jù)庫(kù)連接池 -->
<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="" 造成的 空字符串""無(wú)法轉(zhuǎn)成Number 問(wèn)題-->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.21</version>
</dependency>
<!--EasyPoi導(dǎo)入導(dǎo)出-->
<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導(dǎo)出
*
* @param response response
* @param fileName 文件名
* @param list 數(shù)據(jù)List
* @param pojoClass 對(duì)象Class
*/
public static void exportExcel(HttpServletResponse response, String fileName, Collection<?> list, Class<?> pojoClass) throws IOException {
if (StringUtils.isBlank(fileName)) {
//當(dāng)前日期
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導(dǎo)出,先sourceList轉(zhuǎn)換成List<targetClass>,再導(dǎo)出
*
* @param response response
* @param fileName 文件名
* @param sourceList 原數(shù)據(jù)List
* @param targetClass 目標(biāo)對(duì)象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導(dǎo)出----設(shè)置title---sheetName---要求Collection<?> list是Class<?> pojoClass類型的
*
* @param response response
* @param fileName 文件名
* @param list 數(shù)據(jù)List
* @param pojoClass 對(duì)象Class
*/
public static void exportExcel(HttpServletResponse response, String title, String sheetName, String fileName, Collection<?> list, Class<?> pojoClass) throws IOException {
if (StringUtils.isBlank(fileName)) {
//當(dāng)前日期
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.在實(shí)體類上加注解@Excel
我這邊使用了lombok。getter setter和構(gòu)造方法通過(guò)注解 @Data @AllArgsConstructor進(jìn)行添加,不使用lombok也可手動(dòng)添加。
要導(dǎo)出的數(shù)據(jù)可在實(shí)體類對(duì)應(yīng)屬性上方加**@Excel()注解**。可定義導(dǎo)出列的名稱、寬度,以及性別可區(qū)分化(一般數(shù)據(jù)庫(kù)中存儲(chǔ)的性別為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;
/**
* 商品標(biāo)題
*/
@Excel(name="商品標(biāo)題")
private String title;
/**
* 商品副標(biāo)題
*/
@Excel(name="商品副標(biāo)題")
private String sub_title;
/**
* 商品售價(jià)
*/
@Excel(name="商品售價(jià)")
private Double sale_price;
/**
* 創(chuàng)建者
*/
@Excel(name="創(chuàng)建者")
private Integer create_by;
/**
* 創(chuàng)建時(shí)間
*/
@Excel(name="創(chuàng)建時(shí)間", format = "yyyy-MM-dd")
private Date create_time;
/**
* 修改時(shí)間
*/
@Excel(name="修改時(shí)間", format = "yyyy-MM-dd")
private Date update_time;
/**
* 修改者id
*/
@Excel(name="修改者id")
private Integer update_by;
}
@Excel 作用到filed上面,是對(duì)Excel一列的一個(gè)描述
@Excel 的屬性介紹:


5.Controller
/**
* excel導(dǎo)出
* @param response
*/
@GetMapping("/excel")
@ApiOperation("根據(jù)檢索條件查詢列表,導(dǎo)出excel")
public void export( HttpServletResponse response) throws IOException {
//根據(jù)條件檢索列表
QueryWrapper<Product> queryWrapper = new QueryWrapper();
//根據(jù)條件檢索商品列表
List<Map<String, Object>> list = productService.selectList(queryWrapper);
//將List<Map<String, Object>>結(jié)果集轉(zhuǎn)換成List<ProductExcel>
List<ProductExcel> productList = MapToEntity.setList(list,ProductExcel.class);
//導(dǎo)出excel
ExcelUtils.exportExcel(response,null,productList, ProductExcel.class);
}
setList方法為工具類,用于將List<Map<String, Object>>結(jié)果集轉(zhuǎn)換成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>數(shù)據(jù)轉(zhuǎn)換
* @author qzz
*/
public class MapToEntity {
/**
* List<Map<String, Object>> 到 List<T> 數(shù)據(jù)轉(zhuǎn)換
*/
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())) {
//設(shè)置對(duì)象的訪問(wèn)權(quán)限,保證對(duì)private的屬性的訪問(wèn)
field.setAccessible(true);
//讀取配置轉(zhuǎn)換字段名,并從map中取出數(shù)據(jù)
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;
}
/**
* 字段類型轉(zhuǎn)換
*/
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{
//其他類型轉(zhuǎn)換
return (T) obj.toString();
}
}
return null;
}
}
6.啟動(dòng)項(xiàng)目,進(jìn)行測(cè)試
項(xiàng)目啟動(dòng)成功后,在瀏覽器中輸入 http://localhost:8083/product/excel,進(jìn)行訪問(wèn):

打開導(dǎo)出的excel文檔:

到此這篇關(guān)于SpringBoot+EasyPoi實(shí)現(xiàn)excel導(dǎo)出的文章就介紹到這了,更多相關(guān)SpringBoot實(shí)現(xiàn)excel導(dǎo)出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中EasyExcel實(shí)現(xiàn)Excel文件的導(dǎo)入導(dǎo)出
- SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式
- SpringBoot?整合?EasyExcel?實(shí)現(xiàn)自由導(dǎo)入導(dǎo)出功能
- SpringBoot整合EasyExcel實(shí)現(xiàn)批量導(dǎo)入導(dǎo)出
- springboot實(shí)現(xiàn)excel表格導(dǎo)出幾種常見(jiàn)方法
- SpringBoot整合EasyExcel實(shí)現(xiàn)文件導(dǎo)入導(dǎo)出
- 使用VUE+SpringBoot+EasyExcel?整合導(dǎo)入導(dǎo)出數(shù)據(jù)的教程詳解
- SpringBoot導(dǎo)出Excel的四種實(shí)現(xiàn)方式
- springboot實(shí)現(xiàn)對(duì)接poi 導(dǎo)出excel折線圖
相關(guān)文章
Java Spring分別實(shí)現(xiàn)定時(shí)任務(wù)方法
這篇文章主要為大家詳細(xì)介紹了Java與Spring設(shè)置動(dòng)態(tài)定時(shí)任務(wù)的方法,定時(shí)任務(wù)的應(yīng)用場(chǎng)景十分廣泛,如定時(shí)清理文件、定時(shí)生成報(bào)表、定時(shí)數(shù)據(jù)同步備份等2022-07-07
springBoot集成Ollama大模型及流式傳輸?shù)膯?wèn)題小結(jié)
Ollama是一個(gè)用于部署和運(yùn)行各種開源大模型的工具,它支持多種平臺(tái)和設(shè)備,包括Windows、Mac和Linux,甚至可以在樹莓派等輕量級(jí)設(shè)備上運(yùn)行,這篇文章主要介紹了springBoot集成Ollama大模型及流式傳輸?shù)膯?wèn)題小結(jié),需要的朋友可以參考下2025-04-04
構(gòu)建Java樹結(jié)構(gòu)的三種實(shí)現(xiàn)方法
這篇文章主要介紹了構(gòu)建Java樹結(jié)構(gòu)的三種實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-06-06
JAVA8如何妙用Optional解決NPE問(wèn)題詳解
在Java中,null代表一個(gè)不存在的對(duì)象,如果對(duì)它進(jìn)行操作就會(huì)拋出java.lang.NullPointerException異常,下面這篇文章主要給大家介紹了關(guān)于JAVA8如何妙用Optional解決NPE問(wèn)題的相關(guān)資料,需要的朋友可以參考下2018-06-06
Mybatis-plus常見(jiàn)的坑@TableField不生效問(wèn)題
這篇文章主要介紹了Mybatis-plus常見(jiàn)的坑@TableField不生效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
MyBatis-Plus整合金倉(cāng)數(shù)據(jù)庫(kù)KingbaseES的實(shí)戰(zhàn)指南
隨著數(shù)字中國(guó)建設(shè)的深入推進(jìn),國(guó)產(chǎn)數(shù)據(jù)庫(kù)在關(guān)鍵業(yè)務(wù)系統(tǒng)中扮演著越來(lái)越重要的角色,本文將通過(guò)一個(gè)電商系統(tǒng)的實(shí)戰(zhàn)案例,深入探討MyBatis-Plus整合KingbaseES的詳細(xì)步驟吧2025-10-10
如何解決websocket開啟多個(gè)頁(yè)面訪問(wèn)同一個(gè)連接會(huì)失效的問(wèn)題
使用WebSocket時(shí),若多個(gè)頁(yè)面訪問(wèn)同一個(gè)WebSocket連接可能會(huì)導(dǎo)致連接失效,遇到這個(gè)問(wèn)題時(shí),可以通過(guò)在SpringBoot中使用@ServerEndpoint注解并添加@Component來(lái)解決,出現(xiàn)連接錯(cuò)誤通常是因?yàn)閃ebSocket連接接收到的是一個(gè)GET請(qǐng)求2024-09-09
詳解spring cloud中使用Ribbon實(shí)現(xiàn)客戶端的軟負(fù)載均衡
這篇文章主要介紹了詳解spring cloud中使用Ribbon實(shí)現(xiàn)客戶端的軟負(fù)載均衡,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Jrebel License Server 激活 IDEA-Jrebel-在線-
這篇文章主要介紹了Jrebel License Server 激活 IDEA-Jrebel-在線-離線-均適用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12

