ARTICLE · 1035580
jquick-pdf 超详细入门教程:Java 轻量级 HTML 模板生成 PDF 工具
jquick-pdf 超详细入门教程:Java 轻量级 HTML 模板生成 PDF 工具
引入
Java 后端做 PDF 导出,最先遇到的往往不是业务难题,而是排版难题:用底层 API 逐个创建页面、字体、段落与表格,代码会迅速膨胀成一套“坐标计算器”,改一个标题或间距就要重新编译;中文字体、长文本分页与服务端输出,又会变成隐性维护成本。jquick-pdf 把数据和版式分开:Java 准备数据,类 HTML 模板描述页面,渲染器输出 PDF。本文先走通一次完整生成。
核心讲解
版本基线与入口类
本文以仓库事实 io.github.paohaijiao:jquick-pdfx:4.0.0 和 JDK 8+ 为准。核心入口是 com.github.paohaijiao.executor.JQuickPdfFactory,它接收模板、变量与页面配置,返回 PDF 的 byte[]。模板常用 <pdf><body>,固定文字必须用单引号(如 '订单确认单'),变量用 {...},已注册资源替换 &{...}。
布局与分页:按字体、边距与尺寸计算位置,并在超出页面时处理分页。 渲染输出:PDFBox 渲染器写入内存流,工厂取出最终字节。 工厂内部持有
JContext与JPdfConfig,因此一次请求应创建一次工厂,不要跨请求复用带有业务变量的实例。三种执行方式对比
方法 模板来源 适用场景 executeContent(String)内存字符串 单元测试、动态拼装的短模板 executeResource(String)classpath 资源 随制品发布的版本化模板,如 "report.txt"executeFile(String)磁盘文件 外置模板目录、需要单独更新的版式 三者都返回
byte[],既可写文件,也可直接写 HTTP 响应流。bind 与 bindAll 语义
bind(String,Object)绑定单变量,bindAll(Map<String,Object>)批量绑定;变量名必须与{name}只做取值替换,&{name}用于图表、模板、树或 SVG 等已注册资源。变量应通过绑定传入,禁止把用户输入拼进标签或style,否则可能破坏语法并引入注入风险。样式与单位要点
样式写在
style属性中,以分号分隔,属性名支持驼峰与连字符互为别名,可在同一声明中混用。尺寸可用px、pt、mm、cm、in,px按 96 DPI 折算(1px = 0.75pt)。常用属性包括width、height、minHeight、maxWidth、relativePosition、margin*、padding*、verticalAlignment、backgroundColor、border、borderRadius、opacity;文字可用fontFamilyNames、fontSize、fontColor、bold、italic、underline、textAlignment、characterSpacing。border采用“类型 宽度 颜色”,如solid 1px #999;borderRadius支持 1~4 个值。颜色支持颜色名、#RRGGBB、rgb()/rgba()与linear-gradient。需要提前知道的边界
模板循环指令(如
for/each)、rowSpan/colSpan合并单元格、直接渲染网络 URL 图片、表单提交动作与提交 URL、全局分页背景或全局水印、keepTogether绝对禁止分页,这些能力在本文基线下均未证实,不应写进方案假设。实战说明
Maven 依赖
使用 JDK 8+、Maven 3.6+,
pom.xml只需加入核心依赖:<dependency><groupId>io.github.paohaijiao</groupId><artifactId>jquick-pdfx</artifactId><version>4.0.0</version></dependency>运行时由 Maven 传递引入 Apache PDFBox 3.0.x、ANTLR4 runtime 与 SLF4J API;模板由 ANTLR4 解析、PDFBox 直接绘制,无浏览器、无 headless Chrome、无本地动态库。首次接入先执行
mvn dependency:tree排除版本冲突,再运行静态模板验证链路。QuickStartPdf 完整示例
以下类可作为普通 Java 程序直接运行,输出当前目录的
quick-start.pdf:import com.github.paohaijiao.executor.JQuickPdfFactory;import java.nio.file.Files;import java.nio.file.Paths;public class QuickStartPdf {public static void main(String[] args) throws Exception {String template = ""+ "<pdf><body>"+ "<h1style=\"fontSize:24;textAlignment:center;fontColor:#1f4e79\">'订单确认单'</h1>"+ "<p>'客户:'{orderNo}</p>"+ "<tablestyle=\"width:520px;border:solid1px #999\">"+ "<tr><th>'商品'</th><th>'数量'</th><th>'金额'</th></tr>"+ "<tr><td>'Java 技术书'</td><td>'2'</td><td>'98.00'</td></tr>"+ "</table></body></pdf>";// 为本次文档绑定业务变量并执行模板byte[] pdf = new JQuickPdfFactory().bind("customer", "张三").bind("orderNo", "NO-2026001").executeContent(template);Files.write(Paths.get("quick-start.pdf"), pdf);}}效果如下

结果预期与验证
执行后应得到可正常打开的
quick-start.pdf:标题居中呈蓝色,变量替换为实际值,表格带 1px 灰色边框。验证顺序固定为“文件生成 → 可打开 → 中文正常 → 数据一致 → 分页符合预期”;失败时先查标签闭合与单引号,再查绑定键名与样式。数据准备与选型边界
报表通常在服务层把金额、日期与状态格式化为展示值,再通过
bind注入模板,从而不被 ORM 字段名、空值与业务枚举牵着走;列表用<list><li>,明细用<table>,图片用<image src="..." alt="...">,分页可用样例验证过的<htmlPageBreak>或<areaBreak>指定。选型上:相比 iText 与 PdfBox 的底层 API,它更适合结构化文档与快速迭代;相比浏览器截图,它无需 Chrome,部署更轻;但完整网页兼容与浏览器专属 CSS 仍需评估其他方案。总结
五个节点决定成败:读入、解析、绑定、布局分页、渲染输出,排查应逐层验证。 语法固定:文本用单引号,变量用 ${name},资源用&{name},样式以分号分隔且支持驼峰/连字符别名。工程固定:先跑通静态模板,再依次加入绑定、样式、分页与真实数据。
适用边界与常见误区:它面向规则明确的结构化业务文档,不是完整 HTML/CSS 实现,也不能替代底层绘图库;最常见的错误是遗漏文本单引号、跨请求复用携带变量的工厂、把用户输入拼进模板,以及在服务器上忽略中文字体。
版本基线:jquick-pdfx 4.0.0、JDK 8+;许可证与版本强相关,上线前请核对 README 版本对照表;更多示例见 GitHub 仓库。