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

java使用freemarker模板生成html再轉為pdf

 更新時間:2025年04月07日 15:14:41   作者:ByteX  
這篇文章主要為大家詳細介紹了java如何使用freemarker模板生成html,再利用iText將生成的HTML轉換為PDF文件,感興趣的小伙伴可以參考下

1.freemarker模板生成html

添加Maven依賴

在pom.xml文件中添加以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

創(chuàng)建Freemarker模板

新建一個HTML文件,例如table.ftl,然后在其中編寫HTML模板,包括表格的頭部、內容和尾部等部分。具體可以參考下面這個例子:

<table border="1">
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Age</th>
        </tr>
    </thead>
    <tbody>
    <#list users as user>
        <tr>
            <td>${user.id}</td>
            <td>${user.name}</td>
            <td>${user.age}</td>
        </tr>
    </#list>
    </tbody>
</table>

上面的模板中使用了Freemarker的指令語法來實現(xiàn)動態(tài)生成表格內容,包括使用<#list>標簽來遍歷用戶列表,并使用${}語法來輸出用戶信息。

創(chuàng)建Controller方法

在Controller中編寫一個方法來獲取用戶列表,然后渲染上面的模板并返回HTML內容。示例代碼如下:

@Controller
public class UserController {
    @GetMapping("/users")
    public String userList(Model model) {
        List<User> users = new ArrayList<>();
        users.add(new User(1, "Tom", 18));
        users.add(new User(2, "Jerry", 20));
        users.add(new User(3, "John", 22));
        model.addAttribute("users", users);
        return "table";
    }
}

上面的方法使用@GetMapping注解來處理請求,然后創(chuàng)建一個用戶列表,并將其添加到模型中。最后返回table字符串,代表要使用的HTML模板文件。

運行項目

運行Spring Boot應用程序,然后使用瀏覽器訪問http://localhost:8080/users,即可看到動態(tài)生成的HTML表格。

注意:上面的例子僅供參考,實際應用中需要根據自己的需求進行修改擴展。

2.利用iText將生成的HTML轉換為PDF文件

理解了freemarker生成html的步驟以后,就可以利用iText把html生成pdf文件了。

1.編寫轉換代碼

添加Maven依賴

在pom.xml文件中添加以下依賴:

<dependency>
<groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.1</version>
</dependency>

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

<!-- 支持css樣式渲染 -->
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-itext5</artifactId>
    <version>9.0.9</version>
</dependency>

2.編寫轉換代碼

在SpringBoot應用程序中創(chuàng)建一個Service或者Controller類,然后編寫HTML轉PDF的代碼。

freeMarker轉換為html的方法:

public class HtmlGenerator {

???????    public static String generate(String template, Map<String, Object> variables) throws IOException, TemplateException, IOException {
     
        Configuration config = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        config.setClassForTemplateLoading(HtmlGenerator.class, "/filePath");
        //讀取模板文件地址
        config.setDefaultEncoding("UTF-8");
        //獲取模板文件
        Template tp = config.getTemplate(template);
        StringWriter stringWriter = new StringWriter();
        BufferedWriter writer = new BufferedWriter(stringWriter);
        tp.setEncoding("UTF-8");
        //把map數據寫入
        tp.process(variables, writer);
        String htmlStr = stringWriter.toString();
        writer.flush();
        writer.close();
        return htmlStr;
    }
}

/filePath為項目中的ftl文件相對路徑。

html生成pdf的方法:

public class PdfDocumentGenerator {
    private static final Logger logger = LoggerFactory.getLogger(PdfDocumentGenerator.class);

    /**
     * Output a pdf to the specified outputstream
     * 
     * @param htmlStr
     *            the htmlstr
     * @param out
     *            the specified outputstream
     * @throws Exception
     */
    public static void generate(String htmlStr, OutputStream out)
            throws Exception {
        DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
        df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant
        df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant
        DocumentBuilder builder = df.newDocumentBuilder();
        org.w3c.dom.Document doc = builder.parse(new ByteArrayInputStream(htmlStr
                .getBytes()));
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(doc, null);
        renderer.layout();
        renderer.createPDF(out);
        out.close();
    }
    
    public static void generatePlus(String htmlStr, OutputStream out) throws IOException, DocumentException {
        final String charsetName = "UTF-8";
        
        Document document = new Document(PageSize.A4, 30, 30, 30, 30);
        document.setMargins(30, 30, 30, 30);
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();
        
        // html內容解析
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(
                new CssAppliersImpl(new XMLWorkerFontProvider() {
                    @Override
                    public Font getFont(String fontname, String encoding,
                                        float size, final int style) {
                        if (fontname == null) {
                       
                            fontname = getChineseFont();      
                        }
                        return super.getFont(fontname, encoding, size,
                                style);
                    }
                })) {
            @Override
            public HtmlPipelineContext clone()
                    throws CloneNotSupportedException {
                HtmlPipelineContext context = super.clone();
                try {
                    ImageProvider imageProvider = this.getImageProvider();
                    context.setImageProvider(imageProvider);
                } catch (NoImageProviderException e) {
                }
                return context;
            }
        };
        
        // 圖片解析
        htmlContext.setImageProvider(new AbstractImageProvider() {
            
            String rootPath = PdfDocumentGenerator.class.getResource("/").getPath();
            
            @Override
            public String getImageRootPath() {
                return rootPath;
            }

            @Override
            public Image retrieve(String src) {
                if (StringUtils.isEmpty(src)) {
                    return null;
                }
                try {
                    Image image = Image.getInstance(new File(rootPath, src).toURI().toString());
                    // 圖片顯示位置
                    image.setAbsolutePosition(400, 400);        
                    if (image != null) {
                        store(src, image);
                        return image;
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                return super.retrieve(src);
            }
        });
        htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());
        
        // css解析
        CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        cssResolver.setFileRetrieve(new FileRetrieve() {
            @Override
            public void processFromStream(InputStream in,
                                          ReadingProcessor processor) throws IOException {
                try (
                        InputStreamReader reader = new InputStreamReader(in, charsetName)) {
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                }
            }

            // 解析href
            @Override
            public void processFromHref(String href, ReadingProcessor processor) throws IOException {
                InputStream is = PdfDocumentGenerator.class.getResourceAsStream("/" + href);
                try (InputStreamReader reader = new InputStreamReader(is,charsetName)) {
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });

        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
        Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
        XMLWorker worker = null;
        worker = new XMLWorker(pipeline, true);
        XMLParser parser = new XMLParser(true, worker, Charset.forName(charsetName));
        try (InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes())) {
            parser.parse(inputStream, Charset.forName(charsetName));
        }
        document.close();
    }

    /**
     * 獲取中文字體位置 
     * @return
     */
    public static String getChineseFont() {
        String chineseFont = null;
        chineseFont = Object.class.getResource("/").getPath() + "font/simsun.ttc";
        if(!new File(chineseFont).exists()){
            throw new RuntimeException("字體文件不存在!"+chineseFont);
        }

        return chineseFont;
    }
}

運行測試方法:

public class Pdfdest {
    public static void main(String[] args) throws Exception {
        String outputFile = "d:/test1.pdf";
        Map<String, Object> map = new HashMap<>();
        map.put("XXX", "測試");
        //生成工具,下面有代碼
        String htmlStr = HtmlGenerator.generate("test.ftl", map);
        //生成工具,下面有代碼
        OutputStream out = new FileOutputStream(outputFile);
        PdfDocumentGenerator.generatePlus(htmlStr,out);
    }
}

準備一個test.ftl放到resource/filePath下,當然字體最好也放到resource/font下,運行時需要使用。

test.ftl的代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"></meta>
    <style>

        @page {
            @top-center { content: element(header) }
        }
        @page {
            @bottom-center { content: element(footer) }
        }
        .apply {
            margin: 0 auto;
            padding: 0 30px;
        }
        .title {
            margin-top: 40px ;
            text-align: center;
            font-weight: bold;
        //字體需要和后臺對應上
        font-family: SimSun;
            font-weight: bold;
            font-size: 20px;
            color: #333333;
            letter-spacing: 0;
        }
        .table {
            border-collapse: collapse;
            width: 100%;
            margin-top: 30px;
            font-family: SimSun;
            font-size: 14px;
            color: #111111;
            letter-spacing: 0.54px;
        }
        .label {
            background-color: #E6E6E6;
            width: 20%;
        }
        .normaltd {
            padding: 10px 0;
        }
        .maxtd {
            height: 250px;
        }
        .value {
            width: 30%;
            padding-left: 10px;
        }
        .apply {
            margin: 0 auto;
            padding: 0 30px;
        }
        .title {
            margin-top: 40px ;
            text-align: center;
            font-weight: bold;
        //字體需要和后臺對應上
        font-family: SimSun;
            font-weight: bold;
            font-size: 20px;
            color: #333333;
            letter-spacing: 0;
        }
        .table {
            width: 100%;
            margin-top: 30px;
            font-family: SimSun;
            font-size: 14px;
            color: #111111;
            letter-spacing: 0.54px;
        }
        .label {
            background-color: #E6E6E6;
            width: 20%;
        }
        .normaltd {
            padding: 10px 0;
        }
        .maxtd {
            height: 250px;
        }
        .value {
            width: 30%;
            padding-left: 10px;
        }

        tr {
            page-break-inside: avoid;
            page-break-after: auto;
        }
    </style>
</head>

<body style="font-family: SimSun">
<div class="apply">
    <p class="title">申請單</p>
    <table border="1" cellspacing="0" class="table">
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">XXX</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr >
            <td valign="middle" colspan="1" class="label maxtd" align="center">XXX</td>
            <td valign="middle" colspan="3" class="maxtd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">XXX</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr >
            <td valign="middle" colspan="1" class="label maxtd" align="center">XXX</td>
            <td valign="middle" colspan="3" class="maxtd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td colspan="1" class="label normaltd" align="center">XXX</td>
            <td colspan="3" class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">XXX</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
        <tr>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
            <td class="label normaltd" align="center">XXX</td>
            <td class="normaltd value">${XXX}</td>
        </tr>
    </table>
</div>
</body>
</html>

執(zhí)行就可以看到生成的pdf文件了,文件路徑在d:/test1.pdf。

到此這篇關于java使用freemarker模板生成html再轉為pdf的文章就介紹到這了,更多相關java freemarker生成html內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java 判斷實體對象及所有屬性是否為空的操作

    Java 判斷實體對象及所有屬性是否為空的操作

    這篇文章主要介紹了Java 判斷實體對象及所有屬性是否為空的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 使用位運算、值交換等方式反轉java字符串的多種方法(四種方法)

    使用位運算、值交換等方式反轉java字符串的多種方法(四種方法)

    這篇文章主要介紹了使用位運算、值交換等方式反轉java字符串,本文通過四種方式給大家講解,給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Spring Gateway基本使用示例小結

    Spring Gateway基本使用示例小結

    Springcloud Gateway使用了Webflux中的reactor-netty響應式編程組件,底層使用了Netty通訊框架,具體一些特征,本文結合實例代碼對Spring Gateway使用給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2023-11-11
  • Java父線程(或是主線程)等待所有子線程退出的實例

    Java父線程(或是主線程)等待所有子線程退出的實例

    下面小編就為大家分享一篇Java父線程(或是主線程)等待所有子線程退出的實例,具有很好的參考價值,希望對大家有所幫助
    2017-11-11
  • idea解決程序包不存在報錯的八種解決方法

    idea解決程序包不存在報錯的八種解決方法

    這篇文章主要介紹了idea解決程序包不存在報錯的八種解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-02-02
  • Springboot實現(xiàn)全局自定義異常的方法詳解

    Springboot實現(xiàn)全局自定義異常的方法詳解

    這篇文章主要介紹了Springboot實現(xiàn)全局自定義異常的方法詳解,SpringBoot的項目已經對有一定的異常處理了,但是對于我們開發(fā)者而言可能就不太合適了,因此我們需要對這些異常進行統(tǒng)一的捕獲并處理,需要的朋友可以參考下
    2023-11-11
  • Java字符串轉時間簡單示例代碼

    Java字符串轉時間簡單示例代碼

    這篇文章主要給大家介紹了關于Java字符串轉時間的相關資料,在Java中字符和字符串常常需要相互轉化,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2023-08-08
  • 淺談java隨機數的陷阱

    淺談java隨機數的陷阱

    這篇文章主要介紹了淺談java隨機數的陷阱,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • SpringMvc使用GoogleKaptcha生成驗證碼

    SpringMvc使用GoogleKaptcha生成驗證碼

    這篇文章主要為大家詳細介紹了SpringMvc項目中使用GoogleKaptcha 生成驗證碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • 重寫hashCode()和equals()方法詳細介紹

    重寫hashCode()和equals()方法詳細介紹

    這篇文章主要介紹了重寫hashCode()和equals()方法詳細介紹,涉及重寫equals()方法,重寫hashCode()方法,重寫equals()而不重寫hashCode()的風險等相關內容的介紹,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01

最新評論