关于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. 弹出table页面--hq

    function queryRelation(tableID,prosourceID){ //弹出页面  debugger; initqueryRelationGrid(tableID,prosour ...

  2. 关于GitHub在VS中出现“已经存在master版本,无法……”的错误解决方案

    引用:http://www.cnblogs.com/SmallZL/p/3637613.html(这篇已经很详细说明如何使用Vs+GitHub),我这里做补充: VS2013已经集成了Git一部分控件 ...

  3. ife task0001页面实现细节问题总结

    好久没写css了,突然对重构页面陌生了许多.不过也没什么,前面几个月一直扩充知识面,偏重了理论技术学习,结果还不算遗憾.昨天重拾css,针对问题做点总结: 一.语义化方面 1.HTML5新标签使用 标 ...

  4. matlab实现M/M/1排队系统

    Matlab实现. 分为主函数 MyLine 和被调用函数 Func. 主函数 MyLine 实现在 Func 函数的基础上实现序贯法, 将平均等待队长作为每次模拟的 X,求出置信区间.Func 函数 ...

  5. bzoj 5329: [Sdoi2018]战略游戏

    Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着 ...

  6. [转]<加密算法c#>——— 3DES加密之ECB模式 和 CBC模式

    本文转自:http://www.cnblogs.com/qq278360339/archive/2013/06/05/3119222.html 最近 一个项目.net 要调用JAVA的WEB SERV ...

  7. json中定义数组

    我们经常会看到在js中定义普通函数: function f1(a,b){ console.log(a+b); } f1(); 今天我们看一下如何在json里边定义函数并调用: var json = { ...

  8. css rgba/hsla知识点讲解及半透明边框

    一.RGBA(R,G,B,A) 参数: R:红色值.正整数 | |百分数 G:绿色值.正整数 | |百分数 B:蓝色值.正整数 | |百分数 A:Alpha透明度.取值0~1之间. 说明:此色彩模式与 ...

  9. ArcGIS for Server安全与LDAP配置

    ArcGIS for Server安全与LDAP配置 1.安全性概述 ArcGIS Server使用基于角色的访问控制来管理对受保护资源的访问.访问GIS资源的权限只能分配给角色.单独的用户只能通过从 ...

  10. Git 几个重要操作指令对比

    1.git merge 和 git rebase https://blog.csdn.net/wh_19910525/article/details/7554489 http://gitbook.li ...