关于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. mongoDB--万能的$关键字

    之前哥的博客写了增删改查的基本用法,其中$set是关键字用来修改值的,但是不关只有set这一个关键字,下面我们就来说一个万能的$关键字 1.常见的等于 大于 小于 大于等于 小于等于 #等于---&g ...

  2. myeclipse更改后台代码不用重启tomcat的方法

    myeclipse更改后台代码不用重启tomcat的方法   方法1:在WebRoot下的META-INF文件夹中新建一个名为context.xml文件,里面添加如下内容(要区分大小写): <C ...

  3. nodejs初探(一)nodejs开发环境搭建

    简介 JavaScript是一种运行在浏览器的脚本.Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快.易于扩展的网络应用.Node.js 使用事件 ...

  4. Ace教你一步一步做Android新闻客户端(四) 优化Bitmap大法

    我计划着把需要用到的知识分解开来写,趁着我们要开发这款客户端的机会把安卓所有移动客户端开发中的技术贯穿其中,也是我自己成长的过程.By Ace in 20160121 我们开发一款新闻客户端程序,它的 ...

  5. SQL中CASE 的用法 转载

    sql语言中有没有类似C语言中的switch case的语句?? 没有,用case   when   来代替就行了.              例如,下面的语句显示中文年月 select getdat ...

  6. python的用户输入和while循环

    1.函数input()工作原理 函数input()让程序暂停运行,等待用户输入一些文本.获取用户输入后,Python将其存储在一个变量中,以方便你使用. (1)获取数值可以用 int()函数 (2)求 ...

  7. ATL模板库中的OLEDB与ADO

    上次将OLEDB的所有内容基本上都说完了,从之前的示例上来看OLEDB中有许多变量的定义,什么结果集对象.session对象.命令对象,还有各种缓冲等等,总体上来说直接使用OLEDB写程序很麻烦,用很 ...

  8. Steps of source code change to executable application

    程序运行的整个过程,学习一下 源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 汇编程序 (assembler) → 目标代码 (o ...

  9. 刚在虚拟机上装的Linux系统,ifconfig后IP地址怎么成了127.0.0.1了

    之前在虚拟机上装了Linux系统,用了一段时间后想删除了重新装一下,然而装完以后ifconfig后,出现的是 [root@localhost ~]# ifconfig lo Link encap:Lo ...

  10. 怎样在vs2013和vs2015中实现自动编译sass

    Visual Studio不论是2013版本还是2015版本要自动编译都需要添加扩展. 添加扩展的方法,路径“工具”->“扩展和更新”,在打开的窗口“搜索”你需要的扩展根据提示“下载”和“安装” ...