Java 实现Freemarker动态HTML转PDF 内带条形码

Java 实现Freemarker动态HTML转PDF 内带条形码

maven jar 准备

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

		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.23</version>
		</dependency>
		<dependency>
			<groupId>net.sf.barcode4j</groupId>
			<artifactId>barcode4j-light</artifactId>
			<version>2.0</version>
			<exclusions>
				<exclusion>
					<groupId>xml-apis</groupId>
					<artifactId>xml-apis</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
准备好字体文件ttf,要不会出现中文乱码,最好放在resource里面

在这里插入图片描述

由于我的project是关于香港的业务,要用到繁体字。

PMingLiU-CN.ttf 是新细明体
MSYHBD.TTF 是微软雅黑,因为标题要加粗,所有要加入一些粗体,不然CSS的font-weight: 600;不能起到加粗的效果。

html 转换pdf PDFUtils.java

由于我的项目是关于信封的内容,因此我本身不知道html显示的内容的高度进行分页,而且业务里要求需要页数和总页数,页脚。所有我只能在生成pdf之后再用itext加入PDF文件的页数及其他。


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.styledxmlparser.css.media.MediaDeviceDescription;
import com.itextpdf.styledxmlparser.css.media.MediaType;

import hk.com.hkbn.itbss.sys.service.helper.SftpHelper;
import hk.com.hkbn.ordletter.bo.GenPdfParam;
import hk.com.hkbn.ordletter.exception.OrdLetterException;

/**
 * HTML  to PDF
 *
 */
public class PDFUtils {
	
	private static final Logger logger = LoggerFactory.getLogger(PDFUtils.class);
	
	public static void htmlFileToPDFStream(GenPdfParam param) throws OrdLetterException  {
		try {
			if (param.getHtmlFile() == null) {
				throw new OrdLetterException("htmlFile is null");
			}
			if (param.getPdfPath() == null) {
				throw new OrdLetterException("output path is null"); 
			}
	        // import font ttf resource
			ConverterProperties converter = new ConverterProperties();
			DefaultFontProvider defaultFontProvider = new DefaultFontProvider(false, false, false);
	        defaultFontProvider.addFont(param.getFontBasePath()+"/PMingLiU-CN.ttf");
	        defaultFontProvider.addFont(param.getFontBasePath()+"/MSYHBD.ttf");
	        converter.setFontProvider(defaultFontProvider);
	        converter.setCharset("UTF-8");
	        //	设置pdf的显示方式,用screen代替print
	 		MediaDeviceDescription mediaDeviceDescription = new MediaDeviceDescription(MediaType.PRINT);
	 		converter.setMediaDeviceDescription(mediaDeviceDescription);
	        
	        //make html to pdf
	        HtmlConverter.convertToPdf(new FileInputStream(param.getHtmlFile()), new FileOutputStream(param.getPdfPath()), converter);
	        logger.info("make pdf finish");
	        //add barcode page number
	        AddBarCodePageNum.addBarCodePageNum(param);
//	        uploadOrdLetter(param.getNewpdfPath(),"kim_uploap_test.pdf");
	        logger.info("upload sftp success");
		} catch (Exception e) {
			e.printStackTrace();
			throw new OrdLetterException("create html to pdf error");
		}
		
	}
	
	public static void uploadOrdLetter(String filepath ,String filename)  {
		try {
			InputStream inputStream = new FileInputStream(filepath);
			SftpHelper sftpHelper = new SftpHelper();
			sftpHelper.uploadFileToOutputPath(inputStream, filename);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
加入页码和页脚以及pdf中的条形码AddBarCodePageNum.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;

import hk.com.hkbn.ordletter.bo.GenPdfParam;
import hk.com.hkbn.ordletter.entity.LetterObj;
import hk.com.hkbn.ordletter.util.Assert;

/**
 * @description PDF add bar code \ page number \ page footer
 */
public class AddBarCodePageNum {

	/**
	 * add bar code and page footer
	 * 
	 * @param orgPdfPath
	 * @param outputPdfPath
	 * @param barcodepath
	 * @return
	 */
	private static final Logger logger = LoggerFactory.getLogger(AddBarCodePageNum.class);
		
	public static void addBarCodePageNum(GenPdfParam param) {
		
		try (// ouput file io
			FileOutputStream fos = new FileOutputStream(param.getNewpdfPath());) {
			// make new file , default size A4
			Document document = new Document(PageSize.A4);
			PdfWriter writer = PdfWriter.getInstance(document,fos);
			document.open();
			
			// PDF content
			PdfContentByte pdfContent = writer.getDirectContent();
			// input pdf file content io steam
			PdfReader reader = new PdfReader(param.getPdfPath());
			// Get resource file total pages
			int num = reader.getNumberOfPages();
			List<LetterObj> nextLetterList = new ArrayList<LetterObj>();
			// keyword
			for (int page = 1; page <= num; page++) {
				LetterObj letterObj = matchPage(reader, page, "@next_Letter_Flag@");
				if (Assert.isNotNull(letterObj)&&letterObj.isNextLetterNumber()) {
					letterObj.setPageNumber(page);
					nextLetterList.add(letterObj);
				}
			}
			logger.info("total page " + num);
			if (num <= 0 || nextLetterList.size() <= 0) {
				logger.info("no page data");
				return;
			}
			Integer grobalInteger = 1;
			Integer prePosition = 0;
			for (LetterObj letterObj : nextLetterList) {
				Integer preNumber = 0;
				if (prePosition > 0) {
					preNumber = nextLetterList.get(prePosition - 1).getPageNumber();
				}
				String barcodevalue = param.getBarCodeValueMap().get(prePosition);
				for (int i = 1; i <= letterObj.getPageNumber() - preNumber; i++) {
					document.newPage();
					// set empty footer
					writer.setPageEmpty(false);
					// add page num and page footer
					onEndPage(writer, document, i, letterObj.getPageNumber() - preNumber, 
							letterObj.getLetterLangFlag(),barcodevalue,prePosition,param);
					PdfImportedPage page = writer.getImportedPage(reader, grobalInteger);
					pdfContent.addTemplate(page, 0, 0);
					if (grobalInteger < nextLetterList.get(nextLetterList.size() - 1).getPageNumber())
						grobalInteger++;
				}
				prePosition++;
			}
			/*
			for (int i = 1; i <= num; i++) {
				  document.newPage(); 
				  // set empty
				  writer.setPageEmpty(false); 
				  //add page num and page footer
				  onEndPage(writer, document,i,num,language,fontBasePath,barcodepath); 
				  PdfImportedPage page =writer.getImportedPage(reader, i); 
				  pdfContent.addTemplate(page, 0, 0);
				}
			*/
			document.close();
			reader.close();
			writer.close();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * Find next letter pageNumber by keyword 
	 * 
	 * @param reader
	 * @param pageNumber 
	 * @param keyword    
	 * @return
	 * @throws Exception
	 */
	public static LetterObj matchPage(PdfReader reader, Integer pageNumber, String keyword) throws Exception {
		PdfReaderContentParser parse = new PdfReaderContentParser(reader);
		// listen
		KeyWordListener renderListener = new KeyWordListener();
		renderListener.setKeyword(keyword);
		renderListener.setPageNumber(pageNumber);
		parse.processContent(pageNumber, renderListener);
		return renderListener.getListenObj();
	}

	/**
	 * make left bar code
	 * 
	 * @param document
	 * @param BarcodePath
	 * @throws DocumentException
	 */
	public static void addBarcode(Document document, String BarcodePath) throws DocumentException {
		try {
			Image image = Image.getInstance(BarcodePath);
			image.setRotationDegrees(90);// image 90
			image.setAbsolutePosition(10, 70);
//			image.scaleAbsolute(200,30);
			// setting image size
			 image.scaleToFit(30,300);
			document.add(image);
		} catch (BadElementException | IOException e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * make first page bar code
	 * 
	 * @param document
	 * @param BarcodePath
	 * @throws DocumentException
	 */
	public static void addFirstPageBarcode(Document document, String BarcodePath) throws DocumentException {
		try {
			Image image = Image.getInstance(BarcodePath);
			image.setAbsolutePosition(52, 595);
			// setting image size
			image.scaleAbsolute(250,30);
//			image.scaleToFit(200,300);
			document.add(image);
		} catch (BadElementException | IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * make page number
	 * 
	 * @param writer
	 * @param document
	 * @param maxPage
	 */
	public static void onEndPage(PdfWriter writer, Document document, Integer currentPage, Integer maxPage,
			String language,  String bracodevalue,Integer LetterRecordCount,GenPdfParam param) {

		try {
			// PDF content
			PdfContentByte pdfContent = writer.getDirectContent();

			pdfContent.saveState();
			pdfContent.beginText();

			int footerFontSize = 8;
			String footerNum = null;
			String fontBasePath = null;
			if ("C".equals(language) || language == null) {
				footerNum = String.format("第 %d 頁, 共 %d 頁", currentPage, maxPage);
				fontBasePath = param.getFontBasePath() + "/PMingLiU-CN.ttf";
			} else if ("E".equals(language)) {
				footerNum = String.format("Page %d , total %d pages", currentPage, maxPage);
				fontBasePath = param.getFontBasePath() + "/PMingLiU-CN.ttf";
			}
			if (currentPage % 2 != 0) {
				// each bar code 
				File barCodeFile = new File(param.getBarCodePath());
				String barcode = genLeftBarCodeValue(currentPage,maxPage,LetterRecordCount);
				BarcodeUtil.genBarCode39(barcode, BarcodeUtil.IMG_TYPE_PNG, barCodeFile);
				// add left bar code
				addBarcode(document, param.getBarCodePath());
			}
			if(currentPage==1 && Assert.isNotNull(bracodevalue)) {
				// bar code 
				File barCodeFile = new File(param.getBarCodePath());
				BarcodeUtil.genBarCode128(bracodevalue, BarcodeUtil.IMG_TYPE_PNG, barCodeFile);
				// add first page bar code
				addFirstPageBarcode(document, param.getBarCodePath());
			}
			// setting font type
			BaseFont baseFont = BaseFont.createFont(fontBasePath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			Font fontDetail = new Font(baseFont, footerFontSize, Font.NORMAL);

			pdfContent.setFontAndSize(baseFont, footerFontSize);
			Phrase phrase = new Phrase(footerNum, fontDetail);
			// get file x pod
			float x = (document.left() + document.right()) / 2;
			// get file y pod
			float y = document.bottom(-10);
			// make page footer
			ColumnText.showTextAligned(pdfContent, Element.ALIGN_CENTER, phrase, x, y - 5, 0);
			// AC-Retention-C content
			Calendar calendar = Calendar.getInstance();
			Date now = calendar.getTime();
			SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
			String footer = "AC-Retention-C-" + format.format(now);
			phrase = new Phrase(footer, fontDetail);
			ColumnText.showTextAligned(pdfContent, Element.ALIGN_CENTER, phrase, x + 200, y - 10, 0);
			pdfContent.endText();
			pdfContent.restoreState();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	/**
	 * get left bar code value
	 * @param currentPage
	 * @param totalPage
	 * @param LetterRecordCount
	 * @return
	 */
	public static String genLeftBarCodeValue(Integer currentPage,Integer totalPage,Integer LetterRecordCount) {
		StringBuilder barcode = new StringBuilder();
		if (currentPage.equals(totalPage)&&currentPage==1) {
			barcode.append("3");
		}else if (currentPage==1) {
			barcode.append("2");
		}else if(currentPage.equals(totalPage)) {
			barcode.append("1");
		}else {
			barcode.append("0");
		}
		//add field 2 (Letter Program Code (001-999))
		barcode.append(String.format("%03d", 6));
		//add field 3 (Letter records count (0001-9999))
		barcode.append(String.format("%04d", LetterRecordCount+1));
		//add field 4 (Insert value *Please check below table)
		barcode.append("1");
		//add field 5 (Current Page Number)
		barcode.append(String.format("%02d", currentPage));
		//add field 6 (total page)
		barcode.append(String.format("%02d", totalPage));
		return barcode.toString();
	}

}

多封pdf信封,设置关键之监听来重置PDF的页数KeyWordListener.java
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;

import hk.com.hkbn.ordletter.entity.LetterObj;

/**
 * use to listener PDF file keywords
 */
public class KeyWordListener implements RenderListener {




    /**
     *match keyword
     */
    private String keyword;
    /**
 	 * match current page
     */
    private Integer pageNumber;
    
    /**
     * has match keyword object 
     */
    private LetterObj listenObj = new LetterObj();
   

    @Override
    public void beginTextBlock() {
        //do nothing
    }

    @Override
    public void renderText(TextRenderInfo renderInfo) {
        //get char
        String content =renderInfo.getText();
        if(content.contains(keyword)) {
        	listenObj.setNextLetterNumber(true);
        	listenObj.setLetterLangFlag(content.substring(content.length()-1));
        }   
    }

    @Override
    public void endTextBlock() {
        //do nothing
    }

    @Override
    public void renderImage(ImageRenderInfo renderInfo) {
        //do nothing
    }

    /**
     * setting need match keyword current page
     * @param pageNumber
     */
    public void setPageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
    }

    /**
     * setting match keyword
     * @param keyword
     */
    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

	public LetterObj getListenObj() {
		return listenObj;
	}

	public void setListenObj(LetterObj listenObj) {
		this.listenObj = listenObj;
	}

	public String getKeyword() {
		return keyword;
	}

	public Integer getPageNumber() {
		return pageNumber;
	}

   

}
freemarker 通过模板文件生成html FreemarkerTemplate.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Locale;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * freemarker make HTML
 *
 */ 
public class FreemarkerTemplate {

	private final Configuration configuration = new Configuration(
			Configuration.VERSION_2_3_23);
	private String charset;

	public FreemarkerTemplate(String charset) {
		this.charset = charset;
		configuration.setEncoding(Locale.CHINA, charset);
		configuration.setClassicCompatible(true);//处理空值未空字符串
	}

	public void setTemplateClassPath(Class resourceLoaderClass,
			String basePackagePath) {
		configuration.setClassForTemplateLoading(resourceLoaderClass,
				basePackagePath);
	}

	public void setTemplateDirectoryPath(String templatePath)
			throws IOException {
		configuration.setDirectoryForTemplateLoading(new File(templatePath));
	}

	public void processToStream(String templateFileName,
			Map<String, Object> dataMap, Writer writer) throws Throwable {
		Template template = configuration.getTemplate(templateFileName);
		template.process(dataMap, writer);
	}

	public void processToFile(String templateFileName,
			Map<String, Object> dataMap, File outFile) throws Throwable {
		Writer writer = new OutputStreamWriter(new FileOutputStream(outFile),
				charset);
		try {
			processToStream(templateFileName, dataMap, writer);
		} catch (Throwable e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				writer.close();
			}
		}
	}

	public String processToString(String templateFileName,
			Map<String, Object> dataMap) throws Throwable {
		Writer writer = new StringWriter(2048);
		try {
			processToStream(templateFileName, dataMap, writer);
			return writer.toString();
		} finally {
			if (writer != null) {
				writer.close();
			}
		}
	}
}

java制作barcode39 和 barcode128 ,生活中比较常见的两种条形码BarcodeUtil.java

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.krysalis.barcode4j.HumanReadablePlacement;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;
/**
 * make bar code
 *
 */
public class BarcodeUtil {
    
	public static final String IMG_TYPE_PNG="image/png";
	
	public static final String IMG_TYPE_GIF="image/gif";
	
	public static final String IMG_TYPE_JPEG="image/jpeg";


	public static File genBarCode39(String msg,String imgType, File file)
			throws IOException {
		FileOutputStream out = new FileOutputStream(file);
		try {
			generateBarCode39(msg,imgType, out);
		} finally {
			if (out != null) {
				out.close();
			}
		}
		return file;
	}

	public static byte[] generateToByte(String msg,String imgType) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			generateBarCode39(msg,imgType, out);
			return out.toByteArray();
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}
	
	public static File genBarCode128(String msg,String imgType, File file)
			throws IOException {
		FileOutputStream out = new FileOutputStream(file);
		try {
			generateBarCode128(msg,imgType, out);
		} finally {
			if (out != null) {
				out.close();
			}
		}
		return file;
	}

	public static void generateBarCode39(String msg, String imgType,OutputStream out)
			throws IOException {
		if (msg == null || out == null) {
			return;
		}
		Code39Bean bean = new Code39Bean();
		int dpi = 150;
		// module width
		double moduleWidth = UnitConv.in2mm(1.0f / dpi);
		bean.setModuleWidth(moduleWidth);
		bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
		bean.setHeight(5);
		bean.setWideFactor(3);
		bean.doQuietZone(false);
	
		BitmapCanvasProvider canvas = new BitmapCanvasProvider(out, imgType,
				dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
		bean.generateBarcode(canvas, msg);
		canvas.finish();
	}
	
	public static void generateBarCode128(String msg, String imgType,OutputStream out)
			throws IOException {
		if (msg == null || out == null) {
			return;
		}
		Code128Bean bean = new Code128Bean();
		int dpi = 100;
		// module宽度 UnitConv.in2mm(1.f / dpi);
		double moduleWidth = 0.4;
		bean.setModuleWidth(moduleWidth);
		bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
		bean.setHeight(10);
		bean.doQuietZone(false);

	
		BitmapCanvasProvider canvas = new BitmapCanvasProvider(out, imgType,
				dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
		bean.generateBarcode(canvas, msg);
		canvas.finish();
	}
}

分页的时候会出现的问题,内容断开,或者分页之后内容不对齐。

可以在css 中给div添加以下属性

.gitf-name{
	clear: both;
	display:inline-block;/*防止内容断开,将外层div设置为一个block*/
}
部分freemarker 代码(有需要可以自己百度查一下)
<!--first part-->
            <div class="container">
                    <div class="give_name">${letterPlan.customerName}</div>
                    <div class="addr-first">
                        <div class="addtitle">BADD1</div>
                        <div style="float: left;">${letterPlan.add1}</div> 
                    </div>
                    <div class="addr">
                        <div class="addtitle">BADD2</div> 
                        <div style="float: left;">${letterPlan.add2}</div> 
                    </div>
                    <div class="addr">
                        <div class="addtitle">BADD3</div> 
                        <div style="float: left;">${letterPlan.add3}</div> 
                    </div>
                    <div class="addr">
                        <div class="addtitle">BADD4</div> 
                        <div style="float: left;">${letterPlan.add4}</div> 
                    </div>
                    <div class="pps">
                    	<div style="clear: both;display:inline-block;height: 5px;">
	                        <div class="pps-left-div">${letterPlan.barcodeID}</div>
	                        <div class="pps-right-div">${letterPlan.customerBarcode}</div> 
                        </div>
                        <div class="bar_code_div">
                            <!-- <img class="barcode" src="${barcodeImg}"></img> -->
                        </div>
                        <div class="send-data">
                            <div class="left-div">發信日期(年/月/日)</div>
                            <div class="middle">:</div>  
                            <div class="right-div">${letterPlan.dateOfDispatch}</div>
                        </div>
                        <div class="useraccount">
                            <div class="left-div">賬戶號碼</div> 
                            <div class="middle">:</div>   
                            <div class="right-div">${letterPlan.accountPPS}</div>
                        </div>
                    </div> 
             </div> 
最终效果图

在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用Freemarker动态生成HTML表格,您可以按照以下步骤: 1. 导入Freemarker依赖 如果您正在使用Maven或Gradle等构建工具,可以将Freemarker添加到项目的依赖中。以下是Maven的依赖: ``` <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.31</version> </dependency> ``` 2. 创建模板文件 在模板文件中,您可以使用Freemarker的语法来定义HTML表格的结构和样式。例如,以下是一个简单的模板文件,它定义了一个包含表头和表格数据的HTML表格: ``` <table> <thead> <tr> <th>Name</th> <th>Age</th> <th>Email</th> </tr> </thead> <tbody> <#list users as user> <tr> <td>${user.name}</td> <td>${user.age}</td> <td>${user.email}</td> </tr> </#list> </tbody> </table> ``` 在模板文件中,`${user.name}`、`${user.age}`和`${user.email}`是Freemarker表达式,它们将在渲染模板时被替换为实际的用户数据。 3. 准备数据 在Java代码中,您需要准备数据以便在模板中使用。您可以将数据放在一个Map对象中,其中每个键值对表示模板中的一个变量和它的值。例如,以下是一个包含三个用户的Map对象: ``` Map<String, Object> data = new HashMap<>(); List<User> users = Arrays.asList( new User("Alice", 30, "alice@example.com"), new User("Bob", 25, "bob@example.com"), new User("Charlie", 35, "charlie@example.com") ); data.put("users", users); ``` 在这里,User是一个自定义的Java类,它具有三个属性:name、age和email。 4. 渲染模板 最后,您需要将数据应用于模板并生成HTML表格。以下是一个简单的方法,使用Freemarker的Template和TemplateExceptionHandler类来完成这个任务: ``` public String generateTable(Map<String, Object> data) throws Exception { Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setClassForTemplateLoading(getClass(), "/templates"); cfg.setDefaultEncoding("UTF-8"); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); Template template = cfg.getTemplate("table.ftl"); StringWriter out = new StringWriter(); template.process(data, out); return out.toString(); } ``` 在这里,“/templates”是存放模板文件的目录,table.ftl是您之前创建的模板文件的名称。当process方法被调用时,Freemarker将使用data中的数据替换模板文件中的表达式,并将结果写入StringWriter对象中。最后,该方法将返回生成的HTML表格字符串。 希望这个简单的例子能帮助您入门Fre ### 回答2: 使用Java中的Freemarker动态生成HTML表格,需要以下步骤: 1. 导入Freemarker库:首先需要在Java项目中导入Freemarker库。可以通过Maven或手动下载jar文件导入。 2. 创建Freemarker配置对象:创建Configuration对象,并进行必要的配置,如设置模板文件的加载路径等。 3. 创建数据模型:创建一个Java对象,用于存储要在HTML表格中展示的数据。可以包含多个属性,比如姓名、年龄等。 4. 加载模板文件:使用Configuration对象加载HTML表格的模板文件。可以是一个已经存在的HTML文件,通过Freemarker的模板语法嵌入需要动态生成的内容。 5. 创建数据模型集合:如果需要在表格中展示多条数据,可以创建一个List或数组,将多个数据模型对象添加到集合中。 6. 填充数据到模板:创建一个Template对象,并使用数据模型集合作为参数,调用process方法将数据填充到模板中。 7. 输出生成的HTML表格:将填充好数据的模板内容输出到一个HTML文件或直接返回给用户。 以下是一个简单的示例代码: ```java import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class FreemarkerExample { public static void main(String[] args) { try { // 创建Freemarker配置对象 Configuration cfg = new Configuration(Configuration.VERSION_2_3_29); cfg.setClassForTemplateLoading(FreemarkerExample.class, "/templates"); // 创建数据模型 List<Map<String, Object>> dataModels = new ArrayList<>(); Map<String, Object> dataModel1 = new HashMap<>(); dataModel1.put("name", "John"); dataModel1.put("age", 25); dataModels.add(dataModel1); Map<String, Object> dataModel2 = new HashMap<>(); dataModel2.put("name", "Alice"); dataModel2.put("age", 30); dataModels.add(dataModel2); // 加载模板文件 Template template = cfg.getTemplate("table_template.ftl"); // 填充数据到模板 Writer out = new OutputStreamWriter(System.out); template.process(dataModels, out); // 输出生成的HTML表格 out.flush(); } catch (IOException | TemplateException e) { e.printStackTrace(); } } } ``` 示例中使用了一个名为`table_template.ftl`的模板文件作为HTML表格的模板,模板中可以使用Freemarker的模板语法嵌入动态生成的内容。 以上就是使用Java中的Freemarker动态生成HTML表格的基本流程,你可以根据实际需求进行修改和扩展。 ### 回答3: 使用Java中的Freemarker库来动态生成HTML表格可以分为以下几个步骤: 1. 引入Freemarker库:传统的方式是下载Freemarker库的jar文件然后将其添加到项目的classpath中。现代方式是使用构建工具如Maven或Gradle来管理依赖。 2. 创建Freemarker配置对象:使用Freemarker的Configuration类来创建一个配置对象。可以通过指定模板文件夹的路径来告诉Freemarker在哪里读取模板。 3. 加载模板:使用配置对象的getTemplate方法来加载模板文件。需要传入模板文件的路径和名称。 4. 创建数据模型:创建一个Java对象作为数据模型,然后将需要在表格中展示的数据放入该对象中。可以使用Map或者POJO来代表数据模型。 5. 合并数据模型和模板:创建一个Writer对象来存储生成的HTML代码。然后使用模板对象的process方法将数据模型和Writer对象作为参数传入,生成HTML代码。 6. 输出HTML代码:将Writer对象中的HTML代码输出到文件或者直接返回给HTTP响应。 总的来说,使用Freemarker库生成HTML表格主要涉及创建Freemarker配置对象、加载模板、创建数据模型、合并数据模型和模板,并最终输出HTML代码。较为复杂的表格可以在模板文件中使用Freemarker的标签和指令来实现动态处理和逻辑控制,以实现更高级的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值