最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot動(dòng)態(tài)導(dǎo)出word文檔實(shí)整教程(復(fù)制即可使用)

 更新時(shí)間:2023年06月12日 08:51:00   作者:努力的螞蟻【你若】  
在我們做項(xiàng)目的時(shí)候會(huì)需要把數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)出到word當(dāng)中,下面這篇文章主要給大家介紹了關(guān)于SpringBoot動(dòng)態(tài)導(dǎo)出word文檔實(shí)整教程的相關(guān)資料,文中的代碼復(fù)制即可使用,需要的朋友可以參考下

背景

最近有一個(gè)需求是需要?jiǎng)討B(tài)導(dǎo)出合同、訂單等信息,導(dǎo)出一個(gè)word文檔供客戶進(jìn)行下載查看。

需要導(dǎo)出的word文件,主要可以分為兩種類型。

  • 導(dǎo)出固定內(nèi)容和圖片的word文檔
  • 導(dǎo)出表格內(nèi)容不固定的word文檔

經(jīng)過對(duì)比工具,我實(shí)踐過兩種實(shí)現(xiàn)方式。第一種是FreeMarker模板來進(jìn)行填充;第二種就是文中介紹的POI-TL。

這里我推薦使用POI-TL。

介紹

POI-TL是word模板引擎,基于Apache POI,提供更友好的API。

目前最新的版本是1.12.X,POI對(duì)應(yīng)版本是5.2.2。

這里需要注意的是POI和POI-TL有一個(gè)對(duì)應(yīng)的關(guān)系。

準(zhǔn)備工作

我使用的POI-TL版本是1.10.0

<dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.7</version>
        </dependency>

快速開始

流程:制作模板->提供數(shù)據(jù)->渲染模板->下載word

注意:需要填充的數(shù)據(jù)需要使用{{}}來表示。

1. 導(dǎo)出固定內(nèi)容和圖片的word文檔

準(zhǔn)備模板

模板保存為docx格式,存放在resource目錄下

提供數(shù)據(jù)

private Map<String, Object> assertMap() {
        Map<String, Object> params = new HashMap<>();
        params.put("name", "努力的螞蟻");
        params.put("age", "18");
        params.put("image", Pictures.ofUrl("http://deepoove.com/images/icecream.png").size(100, 100).create());
        return params;
    }

工具方法

/**
     * 將項(xiàng)目中的模板文件拷貝到根目錄下
     * @return
     */
    private String copyTempFile(String templeFilePath) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templeFilePath);
        String tempFileName = System.getProperty("user.home") + "/" + "1.docx";
        File tempFile = new File(tempFileName);
        try {
            FileUtils.copyInputStreamToFile(inputStream, tempFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tempFile.getPath();
    }
private void down(HttpServletResponse response, String filePath, String realFileName) {
        String percentEncodedFileName = null;
        try {
            percentEncodedFileName = percentEncode(realFileName);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=").append(percentEncodedFileName).append(";").append("filename*=").append("utf-8''").append(percentEncodedFileName);
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
             // 輸出流
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) {
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = bis.read(buff)) > 0) {
                bos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
     * 百分號(hào)編碼工具方法
     * @param s 需要百分號(hào)編碼的字符串
     * @return 百分號(hào)編碼后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }

編寫接口

@RequestMapping("genera")
    public void genera(HttpServletResponse response) {
        //1.組裝數(shù)據(jù)
        Map<String, Object> params = assertMap();
        //2.獲取根目錄,創(chuàng)建模板文件
        String path = copyTempFile("word/1.docx");
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = "D:\\" + fileName;
        try {
            //3.將模板文件寫入到根目錄
            //4.編譯模板,渲染數(shù)據(jù)
            XWPFTemplate template = XWPFTemplate.compile(path).render(params);
            //5.寫入到指定目錄位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供前端下載
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.刪除臨時(shí)文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
    }

對(duì)于圖片的格式,POI-TL也提供了幾種方式來提供支撐。

測(cè)試

請(qǐng)求接口:http://127.0.0.1:1000/file/genera

效果如下:

2. 導(dǎo)出表格內(nèi)容不固定的word文檔

表格動(dòng)態(tài)內(nèi)容填充,POI-TL提供了3種方式。

  • 表格行循環(huán)
  • 表格列循環(huán)
  • 動(dòng)態(tài)表格。

第二種和第三種都可以實(shí)現(xiàn)表格填充,但我個(gè)人感覺第一種更方便一點(diǎn),這里我只介紹【表格行循環(huán)】實(shí)現(xiàn)方式。

LoopRowTableRenderPolicy 是一個(gè)特定場(chǎng)景的插件,根據(jù)集合數(shù)據(jù)循環(huán)表格行。

注意:

  • 模板中有兩個(gè)list,這兩個(gè)list需要置于循環(huán)行的上一行。
  • 循環(huán)行設(shè)置要循環(huán)的標(biāo)簽和內(nèi)容,注意此時(shí)的標(biāo)簽應(yīng)該使用[]

準(zhǔn)備模板

提供數(shù)據(jù)

學(xué)生實(shí)體類

public class Student {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

學(xué)生word類

public class StudentTable {
    private String title;
    private List<Student> studentList;

    private List<Student> studentList1;

    public List<Student> getStudentList1() {
        return studentList1;
    }

    public void setStudentList1(List<Student> studentList1) {
        this.studentList1 = studentList1;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<Student> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
}

表格數(shù)據(jù)

private StudentTable assertData() {
        StudentTable table = new StudentTable();
        table.setTitle("我是標(biāo)題");
        List<Student> studentList = new ArrayList<>();
        Student student = new Student();
        student.setName("張三");
        student.setAge("18");
        studentList.add(student);
        Student student1 = new Student();
        student1.setName("李四");
        student1.setAge("20");
        studentList.add(student1);
        Student student2 = new Student();
        student2.setName("王五");
        student2.setAge("21");
        studentList.add(student2);
        Student student3 = new Student();
        student3.setName("馬六");
        student3.setAge("19");
        studentList.add(student3);
        table.setStudentList(studentList);
        table.setStudentList1(studentList);
        return table;
    }

編寫接口

@RequestMapping("dynamicTable")
    public void dynamicTable(HttpServletResponse response) {
        //1.組裝數(shù)據(jù)
        StudentTable table = assertData();
        //2.獲取根目錄,創(chuàng)建模板文件
        String path = copyTempFile("word/2.docx");
        //3.獲取臨時(shí)文件
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = "D:\\" + fileName;
        try {
            //4.編譯模板,渲染數(shù)據(jù)
            LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
            Configure config =
                    Configure.builder().bind("studentList", hackLoopTableRenderPolicy).bind("studentList1", hackLoopTableRenderPolicy).build();
            XWPFTemplate template = XWPFTemplate.compile(path, config).render(table);
            //5.寫入到指定目錄位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供下載
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.刪除臨時(shí)文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
    }

測(cè)試

請(qǐng)求接口:http://127.0.0.1:1000/file/dynamicTable

效果如下:

總結(jié) 

到此這篇關(guān)于SpringBoot動(dòng)態(tài)導(dǎo)出word文檔實(shí)整教程的文章就介紹到這了,更多相關(guān)SpringBoot動(dòng)態(tài)導(dǎo)出word文檔內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java方法遞歸與輸入輸出深入探索

    Java方法遞歸與輸入輸出深入探索

    這篇文章主要介紹了Java方法遞歸與輸入輸出的相關(guān)資料,方法遞歸是一種在方法內(nèi)部調(diào)用自身的技術(shù),適用于具有遞歸結(jié)構(gòu)的問題,輸入輸出是Java程序與外部世界交互的橋梁,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • Java實(shí)現(xiàn)對(duì)一行英文進(jìn)行單詞提取功能示例

    Java實(shí)現(xiàn)對(duì)一行英文進(jìn)行單詞提取功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)對(duì)一行英文進(jìn)行單詞提取功能,結(jié)合實(shí)例形式分析了java基于StringTokenizer類進(jìn)行字符串分割的相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Nacos Server部署配置全過程

    Nacos Server部署配置全過程

    本文介紹了Nacos的定義、核心功能(服務(wù)注冊(cè)、心跳、發(fā)現(xiàn)、健康檢查等)、單機(jī)和集群部署步驟,以及客戶端服務(wù)的搭建與配置,旨在幫助用戶快速了解和使用Nacos進(jìn)行服務(wù)治理和配置管理
    2025-10-10
  • java并發(fā)編程專題(九)----(JUC)淺析CyclicBarrier

    java并發(fā)編程專題(九)----(JUC)淺析CyclicBarrier

    這篇文章主要介紹了java CyclicBarrier的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java編程—在測(cè)試中考慮多態(tài)

    Java編程—在測(cè)試中考慮多態(tài)

    這篇文章主要介紹了Java編程—在測(cè)試中考慮多態(tài),具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Spring IOC 容器 refresh() 方法

    Spring IOC 容器 refresh() 方法

    Spring容器的refresh()方法是其啟動(dòng)的核心入口,由1個(gè)標(biāo)準(zhǔn)步驟,完成從配置加載到Bean實(shí)例化的全流程,這篇文章給大家介紹Spring IOC 容器 refresh()方法,感興趣的朋友跟隨小編一起看看吧
    2026-05-05
  • SpringBoot讀取Nacos上配置文件的步驟詳解

    SpringBoot讀取Nacos上配置文件的步驟詳解

    在 Spring Boot 應(yīng)用程序中,可以使用 Spring Cloud Nacos 來實(shí)現(xiàn)從 Nacos 服務(wù)注冊(cè)中心和配置中心讀取配置信息,本文介紹如何在 Spring Boot 中讀取 Nacos 上的配置文件的步驟,需要的朋友可以參考下
    2024-03-03
  • 淺析Java模板方法的一種使用方式

    淺析Java模板方法的一種使用方式

    模板方法說白了就是將一段代碼模板化,將通用的代碼段抽取出來,并提供一些自定義的接口去定制的特定位置的某些業(yè)務(wù)功能。本文主要來和大家聊聊它的一種使用方式,希望對(duì)大家有所幫助
    2023-02-02
  • 一文帶你深入了解Java中延時(shí)任務(wù)的實(shí)現(xiàn)

    一文帶你深入了解Java中延時(shí)任務(wù)的實(shí)現(xiàn)

    延時(shí)任務(wù)相信大家都不陌生,在現(xiàn)實(shí)的業(yè)務(wù)中應(yīng)用場(chǎng)景可以說是比比皆是。這篇文章主要為大家介紹幾種實(shí)現(xiàn)延時(shí)任務(wù)的辦法,感興趣的可以了解一下
    2022-11-11
  • 詳解Spring Security的formLogin登錄認(rèn)證模式

    詳解Spring Security的formLogin登錄認(rèn)證模式

    對(duì)于一個(gè)完整的應(yīng)用系統(tǒng),與登錄驗(yàn)證相關(guān)的頁面都是高度定制化的,非常美觀而且提供多種登錄方式。這就需要Spring Security支持我們自己定制登錄頁面,也就是本文給大家介紹的formLogin模式登錄認(rèn)證模式,感興趣的朋友跟隨小編一起看看吧
    2019-11-11

最新評(píng)論

鄂尔多斯市| 北安市| 长宁县| 高清| 志丹县| 浦北县| 中方县| 霞浦县| 泽普县| 德阳市| 中阳县| 嘉鱼县| 凤冈县| 安达市| 义乌市| 延津县| 惠水县| 罗田县| 桂东县| 建昌县| 万山特区| 平山县| 昌黎县| 偃师市| 虞城县| 缙云县| 松原市| 正定县| 湘西| 瓦房店市| 屯留县| 弥渡县| 宿迁市| 潼南县| 精河县| 桃江县| 永清县| 桃园县| 昌江| 姚安县| 富蕴县|