国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

震撼!我用 Spring Boot 封裝了一個通殺全場的 Excel 導(dǎo)出神器,任何數(shù)據(jù)一鍵搞定!

開發(fā) 前端
前陣子,組里一位同事小王又被這問題折磨得抓耳撓腮:“有沒有那種不用寫注解、隨便傳數(shù)據(jù)都能導(dǎo)出的 Excel 工具啊?我這邊二十張表,全長得不一樣。”? 聽完我直接笑出聲 —— 誰還沒被這種需求折磨過?

在企業(yè)開發(fā)中,“導(dǎo)出 Excel” 一直是個繞不過去的痛點(diǎn)。 每次換個表結(jié)構(gòu)、改個字段名,就得新建 DTO、調(diào)整注解、修模板、測樣式——不僅繁瑣,還極易出錯。

前陣子,組里一位同事小王又被這問題折磨得抓耳撓腮:“有沒有那種不用寫注解、隨便傳數(shù)據(jù)都能導(dǎo)出的 Excel 工具???我這邊二十張表,全長得不一樣?!?nbsp;聽完我直接笑出聲 —— 誰還沒被這種需求折磨過?于是我干脆擼了個“通用型 Excel 導(dǎo)出神器”,能自動識別數(shù)據(jù)結(jié)構(gòu)、自動生成表頭、自動輸出 Excel, 無論你傳的是 List<Object> 還是 List<Map>,都能輕松搞定,一次封裝,全場通殺。

設(shè)計思路

核心思想其實(shí)非常樸素: 通過反射分析傳入對象的字段結(jié)構(gòu),用 EasyExcel(或 Apache POI)寫出 Excel 文件。 關(guān)鍵點(diǎn)在于“自動推斷表頭”,也就是說,不用再寫注解或者 DTO,工具會自動識別字段名并生成 Excel 頭部。

  • 如果傳入的是 List<User>:反射獲取字段名(如 idnameage);
  • 如果傳入的是 List<Map>:以第一條記錄的 key 作為表頭。

思路清晰明了,下面直接看代碼。

工具類實(shí)現(xiàn)

文件路徑:

/src/main/java/com/icoderoad/excel/util/ExcelExportUtil.java

代碼如下 :

package com.icoderoad.excel.util;


import com.alibaba.excel.EasyExcel;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;


import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;


/**
 * 通用 Excel 導(dǎo)出工具類
 * 支持 List<Object> 與 List<Map> 數(shù)據(jù)格式
 */
public class ExcelExportUtil {


    /**
     * 通用導(dǎo)出方法
     * @param response 響應(yīng)對象
     * @param data 導(dǎo)出數(shù)據(jù)
     * @param fileName 導(dǎo)出文件名
     */
    public static <T> void export(HttpServletResponse response, List<T> data, String fileName) throws IOException {
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("導(dǎo)出數(shù)據(jù)不能為空");
        }


        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setCharacterEncoding("utf-8");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");


        // 判斷類型:Map 或 普通對象
        if (data.get(0) instanceof Map) {
            writeMapData(response, (List<Map<String, Object>>) data);
        } else {
            writeObjectData(response, data);
        }
    }


    /** 處理 List<Map> 數(shù)據(jù)導(dǎo)出 */
    private static void writeMapData(HttpServletResponse response, List<Map<String, Object>> list) throws IOException {
        List<List<String>> head = new ArrayList<>();
        List<List<Object>> rows = new ArrayList<>();


        Set<String> headers = list.get(0).keySet();
        headers.forEach(k -> head.add(Collections.singletonList(k)));


        for (Map<String, Object> row : list) {
            List<Object> line = new ArrayList<>();
            for (String k : headers) {
                line.add(row.getOrDefault(k, ""));
            }
            rows.add(line);
        }


        EasyExcel.write(response.getOutputStream())
                .head(head)
                .sheet("Sheet1")
                .doWrite(rows);
    }


    /** 處理 List<Object> 數(shù)據(jù)導(dǎo)出 */
    private static <T> void writeObjectData(HttpServletResponse response, List<T> list) throws IOException {
        Class<?> clazz = list.get(0).getClass();
        List<List<String>> head = new ArrayList<>();
        List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
        fields.forEach(f -> head.add(Collections.singletonList(f.getName())));


        List<List<Object>> rows = new ArrayList<>();
        for (T t : list) {
            List<Object> row = new ArrayList<>();
            for (Field f : fields) {
                f.setAccessible(true);
                try {
                    row.add(Optional.ofNullable(f.get(t)).orElse(""));
                } catch (IllegalAccessException e) {
                    row.add("");
                }
            }
            rows.add(row);
        }


        EasyExcel.write(response.getOutputStream())
                .head(head)
                .sheet("Sheet1")
                .doWrite(rows);
    }
}

實(shí)體類與 Controller 示例

路徑:

/src/main/java/com/icoderoad/excel/controller/ExportController.java
package com.icoderoad.excel.controller;


import com.icoderoad.excel.util.ExcelExportUtil;
import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;


/**
 * Excel 導(dǎo)出控制器
 */
@RestController
public class ExportController {


    @Data
    public static class User {
        private Long id;
        private String name;
        private Integer age;


        public User(Long id, String name, Integer age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    }


    /** 示例1:導(dǎo)出固定結(jié)構(gòu)對象 */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws IOException {
        List<User> users = Arrays.asList(
                new User(1L, "張三", 20),
                new User(2L, "李四", 25)
        );
        ExcelExportUtil.export(response, users, "用戶信息");
    }


    /** 示例2:導(dǎo)出動態(tài)結(jié)構(gòu) Map 數(shù)據(jù) */
    @GetMapping("/exportDynamic")
    public void exportDynamic(HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();


        Map<String, Object> row1 = new LinkedHashMap<>();
        row1.put("姓名", "小王");
        row1.put("部門", "研發(fā)部");
        row1.put("薪資", 18000);
        list.add(row1);


        Map<String, Object> row2 = new LinkedHashMap<>();
        row2.put("姓名", "小李");
        row2.put("部門", "測試部");
        row2.put("薪資", 15000);
        list.add(row2);


        ExcelExportUtil.export(response, list, "員工薪資表");
    }
}

細(xì)節(jié)與擴(kuò)展優(yōu)化

在后續(xù)使用中,我還為這個工具做了幾處增強(qiáng)優(yōu)化:

  1. 字段排序控制 可以通過注解(如 `@ExcelColumn(order = 1))控制導(dǎo)出列順序。
  2. 日期格式化 對于 Date 類型字段,默認(rèn)格式化為 yyyy-MM-dd HH:mm:ss,避免直接輸出時間戳。
  3. 空值處理 自動將 null 轉(zhuǎn)為空字符串,防止出現(xiàn) NPE 異常。
  4. 中文表頭映射 支持自定義表頭注解,如 @ExcelColumn("用戶名"),導(dǎo)出時自動映射成中文列名。
  5. 緩存字段定義 當(dāng)導(dǎo)出超大數(shù)據(jù)量時,可緩存字段元數(shù)據(jù)結(jié)構(gòu),減少反射次數(shù),提高性能。

總結(jié)

這套導(dǎo)出工具目前已經(jīng)在多個項(xiàng)目中穩(wěn)定運(yùn)行,支持幾乎所有常見導(dǎo)出場景。 無論是動態(tài)結(jié)構(gòu)的前端數(shù)據(jù),還是固定結(jié)構(gòu)的 Java Bean,只要傳入 List,都能一鍵生成 Excel。

更重要的是:

不用再維護(hù) DTO、注解、模板,告別字段對不上、列順序亂、手工測試?yán)鄣膯栴}。

如果你也經(jīng)常被導(dǎo)出 Excel 折騰,不妨嘗試這樣的通用思路。簡單、穩(wěn)健、可維護(hù)——這才是工程化實(shí)踐的真正魅力。

責(zé)任編輯:武曉燕 來源: 路條編程
相關(guān)推薦

2025-02-17 07:48:45

2025-04-08 01:00:00

Spring開發(fā)系統(tǒng)

2025-09-26 02:00:00

Spring接口開發(fā)

2021-04-23 10:38:52

Spring BootSpringMVC源碼

2022-06-06 08:42:04

spring-boo開發(fā)接口防盜刷

2025-04-17 04:00:00

2025-03-26 00:35:00

Javaweb開發(fā)

2020-03-31 15:03:56

Spring Boot代碼Java

2025-03-28 07:56:39

Spring服務(wù)配置

2022-06-23 08:42:08

配置加密解密

2024-06-17 10:30:38

運(yùn)維IP地址網(wǎng)絡(luò)

2020-09-27 14:13:50

Spring BootJava框架

2021-04-20 23:44:25

Excel工具Java

2023-04-12 16:16:53

微軟開源

2020-08-25 20:10:53

GitHub代碼開發(fā)者

2015-10-09 15:18:24

2020-06-22 07:55:28

接口爬蟲

2022-05-26 10:42:30

數(shù)據(jù)權(quán)限注解

2019-10-11 11:00:53

Nginx神器前端

2020-03-16 17:20:02

異常處理Spring Boot
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

欧美诱惑福利视频| 亚洲精品一区二区在线看| 国产精品每日更新在线播放网址| 欧美最大成人综合网| 午夜先锋成人动漫在线| 欧美变态tickle挠乳网站| 天堂av在线资源| 国产拍欧美日韩视频二区| 一区二区三区视频在线播放| 中文精品在线| 成人激情视频网| 91精品啪在线观看国产手机| 精品欧美乱码久久久久久1区2区 | 亚洲香蕉伊在人在线观| 国产视频一区二区视频| 精品一区二区国语对白| 久久久久久久免费| 亚洲成人免费| 国产成人精品久久| 97久久综合区小说区图片区| 国产亚洲免费的视频看| 草莓视频丝瓜在线观看丝瓜18| 色婷婷精品大视频在线蜜桃视频| 99热一区二区| 性伦欧美刺激片在线观看| 国产精品情侣自拍| 日本成人a网站| 欧美一区二区色| 成人性生交大片免费看中文视频| 久久裸体视频| 涩涩涩999| 久久久精品午夜少妇| 国产伦精品一区二区三区视频黑人| 亚洲一二三区在线观看| 97在线观看免费| 91在线视频| 久久国产视频网| 欧美四级电影网| 亚洲欧洲一区二区| av在线不卡免费| 欧美午夜一区二区福利视频| 欧美视频在线免费| 热久久99这里有精品| 国产91在线视频观看| 中文字幕精品影院| 91精品午夜视频| 蜜桃传媒视频麻豆第一区免费观看 | 欧美激情videos| 久久99国产精品视频| 国产精品午夜视频| 蜜臀av性久久久久蜜臀aⅴ流畅| 欧美日韩在线免费播放| 国产亚洲欧美一级| 日本福利视频导航| 成人福利视频网站| 九色视频成人porny| 久久久激情视频| 国产尤物99| 岛国一区二区三区| 免费高清在线观看免费| 一区二区三区不卡视频在线观看 | 国产精品激情电影| 免费av一区二区三区| 久久国产三级精品| 超碰网在线观看| 色婷婷香蕉在线一区二区| 调教一区二区| 精品少妇一区二区三区日产乱码 | 国模雨婷捆绑高清在线| 亚洲欧美国产另类| 欧美人与拘性视交免费看| 99电影在线观看| 六月婷婷一区| 欧美精品久久久久久久久久久| 国产日韩三级| 中文字幕无码精品亚洲资源网久久| 亚洲国产精品久久艾草纯爱| 亚洲精品成人一区| 人禽交欧美网站免费| 91在线视频免费观看| 在线观看免费版| 日韩精品中文字幕一区| av日韩久久| 国产区一区二区| 欧美国产欧美综合| 2017亚洲天堂1024| 欧美精品videos| 久久精品国产77777蜜臀| 老子影院午夜伦不卡大全| 国产精品一区二区果冻传媒| 日本免费一区二区三区等视频| 男女免费网站| 国产精品爽爽爽| 精品在线网站观看| 九色国产在线观看| 一区二区三区国| 日本精品久久中文字幕佐佐木 | 69精品丰满人妻无码视频a片| 欧美另类高清videos| 欧美视频一区二区三区在线观看| 一区二区三区四区电影| 草莓视频一区| 国产精品美女久久久久久久久久久| 黄色网页网址在线免费| 亚洲曰本av电影| 99久久伊人网影院| 成人在线观看一区| 亚洲成人教育av| **网站欧美大片在线观看| 精品美女在线视频| 亚洲最大网站| 亚洲国产精品毛片av不卡在线| 欧美精品免费在线| 亚洲国产日日夜夜| 蜜桃a∨噜噜一区二区三区| 国产日产欧美视频| 色婷婷综合久久久久| 久久九九99| 亚洲婷婷噜噜| 久久国产一区| 亚洲免费观看高清完整版在线观看熊 | 中文字幕一区二区三区乱码图片| 97超碰人人在线| 亚洲欧美电影在线观看| 久久国产精品影片| 亚洲国产精品成人综合| re久久精品视频| 1024视频在线| 国产美女精品免费电影| 97香蕉超级碰碰久久免费软件 | 青青视频免费在线| 日韩有码在线视频| av伊人久久| 日韩综合久久| 在线视频三区| 在线激情av| 2018日日夜夜| 91久久久在线| 亚洲美女精品成人在线视频| 亚洲日本丝袜连裤袜办公室| 亚洲久久在线| xxx欧美xxx| 色中色在线视频| 97操在线视频| 日韩色av导航| 日韩高清在线观看| 欧美国产激情| 欧美日韩一卡| 激情综合网站| 日韩三级久久| 成人黄色动漫| 日韩免费网站| 日本在线免费网| 国产精品av免费观看| 国产日本欧美一区二区三区在线 | 99一区二区三区| 国产色产综合产在线视频| 亚洲特级毛片| 天堂精品中文字幕在线| 国产精品流白浆在线观看| 日本亚州欧洲精品不卡| 亚洲欧美日本伦理| 欧美私人啪啪vps| 日韩精品乱码免费| 本田岬高潮一区二区三区| 337p粉嫩大胆色噜噜噜噜亚洲| 久久蜜臀中文字幕| 精品亚洲成av人在线观看| 日日摸夜夜添夜夜添亚洲女人| 国产精品国产三级国产| 久久久久国产精品午夜一区| av成人免费在线观看| 日韩欧美一区视频| 日韩欧美区一区二| 日韩中文在线视频| 国产精品旅馆在线| 日韩视频精品| 国产精品久久久久久精| 在线观看麻豆视频| 午夜免费福利在线观看| 成人看片爽爽爽| 国产成人在线观看| 国产精品电影院| 亚洲午夜在线电影| xxav国产精品美女主播| 欧美日本亚洲| 二区中文字幕| caopo在线| 六月丁香久久丫| 亚洲成人在线| 中文字幕字幕中文在线中不卡视频| 日韩精品一区二区三区四区| 欧美肥婆姓交大片| av女优在线播放| heyzo在线| 久久亚洲美女| 亚洲欧美日韩图片| 凹凸日日摸日日碰夜夜爽1| 三级小说欧洲区亚洲区| 一区二区三区精品视频|