关于Java生成HTML,可参考我的这篇文章:FreeMarker之根据模型生成HTML代码

当然了,该篇文章也会给你很多启发,比如,根据html生成html,大家不要小看这个,著名的WordPress博客文章,本质上就是这个机制,每发表一篇文章相当于新生成的一个HTML,内容不一样,样式基本是一致的。

下面进入正题:

一、导入Maven依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foresee</groupId>
<artifactId>mypdf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<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.4.2</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</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>
</dependency> </dependencies>
</project>

二、编写Java代码

package com.beck.util;

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.code39.Code39Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;
import sun.misc.BASE64Encoder; 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 String generateToBase64(String msg,String imgType) throws IOException {
ByteArrayOutputStream ous = new ByteArrayOutputStream();
generateToStream(msg,imgType, ous);
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(ous.toByteArray());
} public static File generateToFile(String msg,String imgType, File file)
throws IOException {
FileOutputStream out = new FileOutputStream(file);
try {
generateToStream(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 {
generateToStream(msg,imgType, out);
return out.toByteArray();
} finally {
if (out != null) {
out.close();
}
}
} public static void generateToStream(String msg, String imgType,OutputStream out)
throws IOException {
if (msg == null || out == null) {
return;
}
Code39Bean bean = new Code39Bean();
// 精细度
int dpi = 150;
// module宽度
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();
} }
package com.beck.util;

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.HashMap;
import java.util.Locale;
import java.util.Map; import freemarker.template.Configuration;
import freemarker.template.Template; 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();
}
}
} }
package com.beck.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer; import com.itextpdf.text.pdf.BaseFont; public class PDFUtils {
private static String fontBasePath=PDFUtils.class.getResource("/").getPath()+"font/";
public static void htmlFileToPDFStream(File htmlFile, OutputStream output,
File imageBaseURL) throws Throwable {
if (htmlFile == null) {
throw new RuntimeException("htmlFile is null");
}
if (output == null) {
throw new RuntimeException("output is null");
} // 生成ITextRenderer实例
ITextRenderer renderer = new ITextRenderer();
// 关联html页面
renderer.setDocument(htmlFile.toURI().toURL().toString());
// 设置获取图片的基本路径
renderer.getSharedContext().setBaseURL(
imageBaseURL.toURI().toURL().toString());
// 设置字体路径,必须和html设置一致
ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(fontBasePath+"msyh.ttc", BaseFont.IDENTITY_H,
BaseFont.NOT_EMBEDDED);
fontResolver.addFont(fontBasePath+"msyhl.ttc", BaseFont.IDENTITY_H,
BaseFont.NOT_EMBEDDED);
fontResolver.addFont(fontBasePath+"msyhbd.ttc", BaseFont.IDENTITY_H,
BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(output);
} public static void htmlFileToPDFFile(File htmlFile, File pdfFile,
File imageBaseURL) throws Throwable {
OutputStream output = new FileOutputStream(pdfFile);
try {
htmlFileToPDFStream(htmlFile, output, imageBaseURL);
} finally {
if (output != null) {
output.close();
}
}
} }
package com.beck.util;

public class Receipt {
private String receiptType;
private double amount;
public String getReceiptType() {
return receiptType;
}
public void setReceiptType(String receiptType) {
this.receiptType = receiptType;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
}

三、在src/main/resources建立HTML页面和相关的文件夹

建立font、images、templates文件夹

文件夹如图所示:

html代码:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>报销单</title>
<style type="text/css" rel="stylesheet">
* {
margin: 0;
padding: 0;
}
body {
font-family: "Microsoft YaHei UI";
font-size: 12px;
max-width: 555px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
font-size: 18px;
color: #000;
font-weight: bold;
}
.comptitle {
height: 66px;
}
.comptitle h2 {
float: left;
height: 66px;
line-height: 66px;
font-size: 14px;
color: #000;
font-weight: bold;
}
.barcode {
width: 162px;
float: right;
padding: 10px 0;
text-align: center;
}
.barcode img {
width: 162px;
height: 30px;
display: table-cell;
vertical-align: middle;
margin-bottom: 5px;
}
.barcode h3 {
font-size: 12px;
color: #000;
}
.stafftbl, .detailstbl, .approverrd {
border-collapse: collapse;
border: 1px solid #f3f3f3;
}
.stafftbl th, .stafftbl td, .detailstbl th, .detailstbl td, .approverrd th, .approverrd td {
height: 20px;
line-height: 20px;
border: 1px solid #f3f3f3;
}
.stafftbl th {
font-weight: normal;
background: #f8f9fd;
text-align: right;
color: #777;
padding-right: 12px;
}
.stafftbl td {
padding-left: 10px;
}
.wrap p {
color: #000;
margin: 12px 0 10px;
}
.detailstbl th, .approverrd th {
font-weight: normal;
color: #777;
background: #f8f9fd;
border: none;
}
.detailstbl td, .approverrd td {
text-align: center;
}
.sum {
background: #f8f9fd;
color: #777;
}
.detailstbl td.sumdata {
text-align: right;
padding-right: 20px;
font-weight: bold;
}
</style>
</head> <body>
<div class="wrap">
<h1>费用报销单</h1>
<div class="comptitle">
<h2>*****有限公司</h2>
<div class="barcode"><img src="${barcodeImg}" alt=""></img>
<h3>${barcode}</h3>
</div>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="stafftbl">
<tbody>
<tr>
<th width="18%">报销人</th>
<td width="32%">${userName}</td>
<th width="18%">填写日期</th>
<td>${submitDate}</td>
</tr>
<tr>
<th>费用所属部门</th>
<td colspan="3">${deptName}</td>
</tr>
<tr>
<th>所属项目</th>
<td colspan="3">运营平台2.0</td>
</tr>
<tr>
<th>报销事由</th>
<td colspan="3">${reimReason}</td>
</tr>
</tbody>
</table>
<p>费用明细</p>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="detailstbl">
<tbody>
<tr> <th width="8%">序号</th>
<th>发票类型</th>
<th width="10%">发票张数</th>
<th width="12%">发票金额</th>
<th width="12%">报销金额</th>
<th>专票税额</th>
<th width="28%">用途</th>
</tr>
<#list receiptList as item>
<tr>
<td >${list_index+1}</td>
<td>${item.receiptType}</td>
<td>1</td>
<td>¥${item.amount}</td>
<td>¥${item.amount}</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</#list>
<tr>
<td colspan="2" class="sum">总报销金额(小写)</td>
<td colspan="5" class="sumdata" >¥259.46</td>
</tr>
<tr>
<td colspan="2" class="sum">总报销金额(大写)</td>
<td colspan="5" class="sumdata" >贰佰伍拾玖元肆角陆分</td>
</tr>
</tbody>
</table>
<p>审批记录</p>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="approverrd">
<tbody>
<tr>
<th width="8%">序号</th>
<th>节点名称</th>
<th>电子签名</th>
<th>签名日期</th>
<th width="8%">操作</th>
<th width="25%">备注</th>
</tr>
<tr>
<td>1</td>
<td>提交</td>
<td>张三/平台支撑部</td>
<td>2018-09-18 16:18:41</td>
<td>提交</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

图片要求必须符合png、jpg等格式,只要是这些格式的都行。

四、编写测试类

package com.beck.util;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID; public class Test { public static void main(String[] args) throws Throwable { String barcode = "12345678910";
String uuid=UUID.randomUUID().toString();
String htmlBasePath="E://Demo//workspace//mypdf//src//main//resources//template";//html的根目录
String tempathBasePath=Test.class.getResource("/").getPath()+"template/";//模板路径
String pdfBasePath="E://Demo//workspace//mypdf//src//main//resources//template";//生成的pdf目录 String barCodePath="E://Demo//workspace//mypdf//src//main//resources//images//"+uuid+".png";
String htmlPath=htmlBasePath+uuid+".html";
String pdfPath=pdfBasePath+uuid+".pdf"; //生成条形码
File barCodeFile=new File(barCodePath);
BarcodeUtil.generateToFile(barcode,BarcodeUtil.IMG_TYPE_PNG,barCodeFile);
System.out.println("生成条形码完成!");
//生成html
FreemarkerTemplate tp=new FreemarkerTemplate("UTF-8");
tp.setTemplateDirectoryPath(tempathBasePath);
//封装数据 start ,必须是Map
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("barcode",barcode);
dataMap.put("barcodeImg",barCodePath);
dataMap.put("userName", "游总");
dataMap.put("submitDate", "2018-09-18");
dataMap.put("deptName", "研发平台");
//费用明细
List<Receipt> receiptList=new ArrayList<Receipt>();//Receipt 必须是public类型的类
Receipt r1=new Receipt();
r1.setReceiptType("普通发票");
r1.setAmount(100); Receipt r2=new Receipt();
r2.setReceiptType("普通发票");
r2.setAmount(100); receiptList.add(r1);
receiptList.add(r2); dataMap.put("receiptList", receiptList);
//封装数据 end
File htmlFile=new File(htmlPath);
tp.processToFile("expense.html", dataMap,htmlFile);
System.out.println("生成html完成!");
//生成pdf
PDFUtils.htmlFileToPDFFile(htmlFile, new File(pdfPath), new File(htmlBasePath));
System.out.println("生成pdf完成!"); } }

运行结果如图所示(控制台打印这些就表示没有问题,如果控制台报错,常见错误就是文件找不到异常,改下路径就可以了,一般情况是没有其他错误):

pdf显示如图:

html显示如图:

条形码显示如图:

源码地址:https://github.com/youcong1996/study_simple_demo.git

如果实在上述代码,不能运行,大家可以将源码移植过来,运行效果是没有问题的。

Java之生成条形码、PDF、HTML的更多相关文章

  1. java zxing 生成条形码和二维吗

    依赖 <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</art ...

  2. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

  3. JAVA生成条形码

    1.下载生成条形码所需要的jar包barcode4j.jar: 2.java生成条形码代码 import java.awt.image.BufferedImage;import java.io.Fil ...

  4. java 生成条形码

    package com.sun.erwei; import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;impo ...

  5. java生成条形码工具类

    package com.runtime.extend.utils.CodeCreate;import java.awt.Color;import java.awt.Font;import java.a ...

  6. Java 动态生成 PDF 文件

    每片文章前来首小诗:   今日夕阳伴薄雾,印着雪墙笑开颜.我心仿佛出窗前,浮在半腰望西天.  --泥沙砖瓦浆木匠 需求: 项目里面有需要java动态生成 PDF 文件,提供下载.今天我找了下有关了,系 ...

  7. Java Itext 生成PDF文件

    利用Java Itext生成PDF文件并导出,实现效果如下: PDFUtil.java package com.jeeplus.modules.order.util; import java.io.O ...

  8. java使用freemark生成word/pdf

    目录 一. 背景 二.实现的技术选型以及遇到的坑 三.最终的效果 2.1 .doc word效果展示 2.1 .docx word效果展示 2.2 docx word转pdf效果展示 三.准备工作及代 ...

  9. Java 图片生成PDF

    public static void main(String[] args) { String imageFolderPath = "E:\\Tencet\\图片\\test\\" ...

随机推荐

  1. (转)Linux curl命令参数详解

    Linux curl命令参数详解 命令:curl在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的http命令行工具.它支持文件的上传和下载,是综合传输工具, ...

  2. ClouderManger搭建大数据集群时ERROR 2003 (HY000): Can't connect to MySQL server on 'ubuntucmbigdata1' (111)的问题解决(图文详解)

    问题详情 相关问题的场景,是在我下面的这篇博客里 Cloudera Manager安装之利用parcels方式(在线或离线)安装3或4节点集群(包含最新稳定版本或指定版本的安装)(添加服务)(Ubun ...

  3. 04-struts2获得参数

    1 struts2 获得参数 1-属性驱动获得参数 1 Demo8Action package www.test.c_param; import java.util.Date; import com. ...

  4. 重入锁--ReentrantLock

    本部分主要参考<java并发编程艺术>一书相关内容,同时参考https://blog.csdn.net/zhilinboke/article/details/83104597,说的非常形象 ...

  5. 查询指定tomcat应用的进程数

    假设应用名称为pear,查询指定tomcat应用pear的进程数: ps -ef |grep "/datong/tomcat-pear/" |grep -v tail | grep ...

  6. Java入门系列-06-运算符

    这篇文章为你搞懂2个问题 java 中的常用运算符有哪些?如何使用? 这些运算符的运算优先级是怎样的? 算数运算符 明显是做数学运算的,包括以下符号: + 加法运算 敲一敲: public class ...

  7. bzoj 5302: [Haoi2018]奇怪的背包

    Description Solution 首先 \(v_1,v_2,v_3...v_n,P\) 能够构成的最小数是 \(gcd(P,v_1,v_2,v_3...v_n)\) 然后 \(gcd(P,v_ ...

  8. ionic2 目录

    首先 ionic2 暂时找不到中文文档.本人英语又很渣.无奈之下只能依赖于百度翻译.完全是已自己理解的方式运作 ,可能里面会有一些偏差之类的 不过我都测试过代码是可以跑通的 只不过讲解的部分可能... ...

  9. js之strict模式

    JavaScript在设计之初,为了方便初学者学习,并不强制要求用var申明变量.这个设计错误带来了严重的后果:如果一个变量没有通过var申明就被使用,那么该变量就自动被申明为全局变量: i = 10 ...

  10. hibernate从零开始到各种映射

    ORM(对象/关系数据库映射) 对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术.它完成了面向对象的编程语言到 ...