欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用FreeMarker來實現(xiàn)Word自定義導出功能

 更新時間:2025年09月26日 11:08:12   作者:保加利亞的風  
Java FreeMarker是一個用Java語言編寫的模板引擎,它可以基于模板來生成文本輸出,并且與Web容器無關,在對一些特定導出功能,使用常規(guī)Excel無法解決的,通常使用Word來實現(xiàn)導出功能,這篇介紹下如何在Java中使用FreeMarker模板注入方式來實現(xiàn)Word導出功能

前言

在對一些特定導出功能,使用常規(guī)Excel無法解決的,通常使用Word來實現(xiàn)導出功能,這篇介紹下如何在Java中使用FreeMarker模板注入方式來實現(xiàn)Word導出功能

導出案例(已作打碼處理)

或者:

準備工作

第一步:maven依賴庫

		<!-- freemarker (用于Word導出)-->
       	<dependency>
	        <groupId>org.freemarker</groupId>
	        <artifactId>freemarker</artifactId>
	        <version>${freemarker.version}</version>
       	</dependency>

第二步:Word導出工具類

import com.zrxt.common.config.RuoYiConfig;
import com.zrxt.common.core.text.CharsetKit;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @ClassName WordUtil
 * @Description 使用Freemarker生成Word文檔工具類
 * @Author
 * @Date 2023/12/14
 **/
public class WordUtil {
    /**
     * 使用Freemarker自動生成Word文檔(磁盤路徑方法)
     *
     * @param dataMap      保存Word文檔中所需要的數(shù)據(jù)
     * @param templatePath 模板文件的絕對路徑
     * @param templateFile 模板文件的名稱
     * @throws Exception
     */
    public static void CreateWord(HttpServletResponse response, Map<String, Object> dataMap, String templatePath, String templateFile) throws Exception {
        Writer out = null;
        try {
            // 設置FreeMarker的版本
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            // 設置Freemarker的編碼格式
            configuration.setDefaultEncoding(CharsetKit.UTF_8);
            // 設置FreeMarker生成Word文檔所需要的模板的路徑
            configuration.setDirectoryForTemplateLoading(new File(templatePath));
            // 設置FreeMarker生成Word文檔所需要的模板名稱
            Template t = configuration.getTemplate(templateFile, CharsetKit.UTF_8);
            // 創(chuàng)建一個Word文檔的輸出流
            out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));
            //FreeMarker使用Word模板和數(shù)據(jù)生成Word文檔
            t.process(dataMap, out);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            assert out != null;
            out.flush();
            out.close();
        }
    }

    /**
     * 使用Freemarker自動生成Word文檔
     *
     * @param dataMap      保存Word文檔中所需要的數(shù)據(jù)
     * @param templatePath 模板文件的路徑(絕對)
     * @param templateFile 模板文件的名稱
     * @throws Exception
     */
    public static void GeneratorWord(HttpServletResponse response, Map<String, Object> dataMap, String templatePath, String templateFile) throws Exception {
        Writer out = null;
        try {
            // 設置FreeMarker的版本
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
            // 設置Freemarker的編碼格式
            configuration.setDefaultEncoding(CharsetKit.UTF_8);
            //相對路徑加載模板方法
            configuration.setTemplateLoader(new ClassTemplateLoader(WordUtil.class,templatePath));
            // 設置FreeMarker生成Word文檔所需要的模板名稱
            Template template  = configuration.getTemplate(templateFile, CharsetKit.UTF_8);
            // 創(chuàng)建一個Word文檔的輸出流
            out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));
            //FreeMarker使用Word模板和數(shù)據(jù)生成Word文檔
            template .process(dataMap, out);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            assert out != null;
            out.flush();
            out.close();
        }
    }

    /**
     * 下載文件
     *
     * @param path     文件的位置
     * @param fileName 自定義下載文件的名稱
     * @param response http響應
     * @param request  http請求
     */
    public static void downloadFile(String path, String fileName, HttpServletResponse response, HttpServletRequest request) {
        try {
            File file = new File(path);
            // 中文亂碼解決
            String type = request.getHeader("User-Agent").toLowerCase();
            if (type.indexOf("firefox") > 0 || type.indexOf("chrome") > 0) {
                // 谷歌或火狐
                fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), "iso8859-1");
            } else {
                // IE
                fileName = URLEncoder.encode(fileName, CharsetKit.UTF_8);
            }
            // 設置響應的頭部信息
            response.setHeader("content-disposition", "attachment;filename=" + fileName);
            // 設置響應內容的類型
            response.setContentType(getFileContentType(fileName) + "; charset=" + CharsetKit.UTF_8);
            // 設置響應內容的長度
            response.setContentLength((int) file.length());
            // 輸出
            outStream(new FileInputStream(file), response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件的內容類型
     */
    private static String getFileContentType(String name) {
        String result = "";
        String fileType = name.toLowerCase();
        if (fileType.endsWith(".png")) {
            result = "image/png";
        } else if (fileType.endsWith(".gif")) {
            result = "image/gif";
        } else if (fileType.endsWith(".jpg") || fileType.endsWith(".jpeg")) {
            result = "image/jpeg";
        } else if (fileType.endsWith(".svg")) {
            result = "image/svg+xml";
        } else if (fileType.endsWith(".doc")) {
            result = "application/msword";
        } else if (fileType.endsWith(".xls")) {
            result = "application/x-excel";
        } else if (fileType.endsWith(".zip")) {
            result = "application/zip";
        } else if (fileType.endsWith(".pdf")) {
            result = "application/pdf";
        } else {
            result = "application/octet-stream";
        }
        return result;
    }


    /**
     * 基礎字節(jié)數(shù)組輸出
     */
    private static void outStream(InputStream is, OutputStream os) {
        try {
            byte[] buffer = new byte[10240];
            int length = -1;
            while ((length = is.read(buffer)) != -1) {
                os.write(buffer, 0, length);
                os.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 檢查存儲生成文件的路徑是否存在,如果不存在則新建路徑.
     *
     * @param directory the directory name, like '\dir-name'
     */
    public static void CheckDownloadPath(String directory) {
        File path = new File(RuoYiConfig.getDownloadPath() + directory);
        if (!path.exists()) {
            path.mkdirs();
        }
    }
}

模板準備

第一步:首先要編寫Word模板,可以參考文章開頭的示例圖片。
第二步:Word模板編寫好后,點擊另存為,然后選擇Word 2003 XML文檔

第三步:保存好后的文件打開,Ctrl+A復制文檔所有內容,然后在線搜索XML格式化在線工具,我這邊提供一個現(xiàn)成的XML格式化在線工具,將內容全部粘貼進去后點擊格式化按鈕。

創(chuàng)建ftl文件

上面所有工作準備好后,就可以在resource目錄下創(chuàng)建一個.ftl文件,然后將格式化后的代碼復制到文件中即可。

測試導出是否完整

Controller層編寫測試代碼,判斷是否可以正常導出

    /**
     * 導出(word)關鍵過程控制詳細信息詳細信息(xml版本)
     */
    @PostMapping(value = "/exportWord")
    public void getInfo(MakeCriticalProcessControl param, HttpServletResponse response) {
        try {
            MakeCriticalProcessControl obj=
                    makeCriticalProcessControlService.selectById(param.getId());
          
            Map<String, Object> context = new HashMap<>();
            context.put("obj", obj);
            WordUtil.GeneratorWord(response, context, "/wordDocumentFtl/make/", "MakeCriticalProcessControl.ftl");
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("導出Word文件失敗,請稍后重試!");
        }
    }

WordUtil.GeneratorWord()方法
第二個參數(shù)context為數(shù)據(jù)庫的數(shù)據(jù),要往word中空白單元格所填充的。
第三個參數(shù)為templatePath – 模板文件的路徑(相對路徑)。
第四個參數(shù)為具體的模板的文件名稱(帶后綴)

注:測試后需檢查格式是否混亂,是否有缺少單元格等情況,如果有則檢查原Word模板并修復然后重新走一遍流程即可

如何將數(shù)據(jù)庫數(shù)據(jù)填充到Word中

ftl文件中的內容是一行一行的順序,也就是從第一行的第一個單元格開始,然后是第一行第二個單元格,第三個單元格…
然后第一行如果結束了,則是第二行第一個單元格、第二個單元格、第三個…

以此類推,所以優(yōu)先找到對應標題的對應數(shù)據(jù)單元格在ftl文件的哪個位置。

如果是單個屬性或對象類型的,可以在controller中使用Map<String, Object> context = new HashMap<>();將數(shù)據(jù)put,然后key作為鍵,在ftl文件中可以把屬性獲取出來。例如下圖

如果涉及到遍歷,將一個list結果導出到word,請看以下案例

如果是遍歷導出的話,則在word模板設置時,只需要設置一行表頭,下方對應一行空的單元格即可,我們要循環(huán)空的單元格,然后將數(shù)據(jù)挨個寫入。

只需要在標題下寫一行即可

在controller中依舊是查詢出對應list,然后put到map中

1:判斷l(xiāng)ist是否為空
2:循環(huán)遍歷list
3:一般<w:tr>表示為行,所以這里的意思就是,list有多少數(shù)據(jù),則就生成多少行
如何要獲取值的話就可以${item.屬性名!}

如果涉及到If語句或者是需要將數(shù)字轉為對應的狀態(tài)

以上就是Java使用FreeMarker來實現(xiàn)Word自定義導出功能的詳細內容,更多關于Java FreeMarker Word自定義導出的資料請關注腳本之家其它相關文章!

相關文章

  • Spring Data JPA中的動態(tài)查詢實例

    Spring Data JPA中的動態(tài)查詢實例

    本篇文章主要介紹了詳解Spring Data JPA中的動態(tài)查詢。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • SpringBoot?整合mapstruct的實現(xiàn)步驟

    SpringBoot?整合mapstruct的實現(xiàn)步驟

    這篇文章主要介紹了SpringBoot整合mapstruct,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 教您如何3分鐘快速搞定EasyExcel導入與導出功能

    教您如何3分鐘快速搞定EasyExcel導入與導出功能

    對于EasyExcel庫,我們可以使用它來實現(xiàn)數(shù)據(jù)的導入和導出,下面這篇文章主要給大家介紹了關于如何3分鐘快速搞定EasyExcel導入與導出功能的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • SpringBoot基本web開發(fā)demo過程解析

    SpringBoot基本web開發(fā)demo過程解析

    這篇文章主要介紹了SpringBoot基本web開發(fā)demo過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • java監(jiān)聽器的實現(xiàn)和原理詳解

    java監(jiān)聽器的實現(xiàn)和原理詳解

    這篇文章主要給大家介紹了關于java監(jiān)聽器實現(xiàn)和原理的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-08-08
  • Spring Boot 如何使用Liquibase 進行數(shù)據(jù)庫遷移(操作方法)

    Spring Boot 如何使用Liquibase 進行數(shù)據(jù)庫遷移(操作方法)

    在Spring Boot應用程序中使用Liquibase進行數(shù)據(jù)庫遷移是一種強大的方式來管理數(shù)據(jù)庫模式的變化,本文重點講解如何在Spring Boot應用程序中使用Liquibase進行數(shù)據(jù)庫遷移,從而更好地管理數(shù)據(jù)庫模式的變化,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • Java基礎入門語法--String類

    Java基礎入門語法--String類

    字符串廣泛應用在Java編程中,在Java中字符串屬于對象,Java 提供了String類來創(chuàng)建和操作字符串,今天給大家介紹Java基礎入門語法--String類的相關知識,感興趣的朋友一起看看吧
    2021-06-06
  • java調用webservice接口,并解析返回參數(shù)問題

    java調用webservice接口,并解析返回參數(shù)問題

    這篇文章主要介紹了java調用webservice接口,并解析返回參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java面向對象設計原則之迪米特法則介紹

    Java面向對象設計原則之迪米特法則介紹

    迪米特法則解決類與類之間耦合度問題,如果類A調用了B類的某一個方法,則這兩個類就形成了一種緊耦合的方式,當B類這個方法發(fā)生變化時,一定會影響A類的執(zhí)行結果。迪米特法則要求每一個類盡可能少的與其他類發(fā)生關系
    2023-02-02
  • Java StringBuilder的用法示例

    Java StringBuilder的用法示例

    這篇文章主要給大家介紹了關于Java StringBuilder用法的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01

最新評論