JQuick-Pdf
JQuick-Pdf 是 JQuick 生态中的 PDF 工具包,面向 Java 端的 生成、渲染与导出:写一份类似 HTML + 内联 CSS 的模板,绑定数据,即可拿到 PDF —— 可以是 byte[]、流或文件。
模板由 ANTLR4 语法解析,并通过 Apache PDFBox 直接绘制到页面上,整条链路 没有浏览器、没有 Headless Chrome、没有本地库,非常适合嵌入服务端、定时任务或桌面应用。
| 模块 | 坐标 | 说明 |
|---|---|---|
jquick-pdfx |
io.github.paohaijiao:jquick-pdfx |
解析器、渲染器、布局引擎与入口 JQuickPdfFactory,多数场景只需引入它 |
jquick-pdf-css |
io.github.paohaijiao:jquick-pdf-css |
CSS 模型:样式属性、单位与颜色 |
jquick-pdf-svg |
io.github.paohaijiao:jquick-pdf-svg |
SVG / ECharts 风格图表生成(30+ 图表类型) |
jquick-pdf-data |
io.github.paohaijiao:jquick-pdf-data |
图表配置模型(JOption、JChart、JTitle、JLegend 等) |
jquick-pdf-font |
io.github.paohaijiao:jquick-pdf-font |
内置中文字体资源,中文渲染零配置 |
- 纯 Java,无外部引擎:不需要 WebKit、Chrome 或任何操作系统级依赖,一个 JVM 进程即可完成渲染。
- HTML/CSS 风格模板:14 种元素,每个元素都支持
style="..."内联样式。 - 两种命名约定:
minHeight(驼峰)与min-height(标准 CSS)等价,可在同一声明中混用。 - 数据绑定:
${variable}绑定普通值,&{resource}引用已注册资源(图表、子模板、树形结构)。 - 30+ 图表类型:柱状图、折线图、饼图、雷达图、散点图、箱线图、热力图、K 线、漏斗图、仪表盘、甘特图、词云、地图、旭日图、矩形树图、拓扑图等,全部为矢量绘制。
- 完整文档能力:自动分页、目录(TOC)、页眉页脚、页码、水印、PDF 加密。
- 中文友好:内置 CJK 字体,中文内容开箱即用。
- 模块化产物:只依赖解析与渲染核心,图表、CSS、字体按需追加。
- Java 8 兼容:发布产物面向 Java 8 字节码。
<dependency> <groupId>io.github.paohaijiao</groupId> <artifactId>jquick-pdfx</artifactId> <version>4.1.0</version></dependency>implementation 'io.github.paohaijiao:jquick-pdfx:4.1.0'图表能力为可选依赖:
<dependency> <groupId>io.github.paohaijiao</groupId> <artifactId>jquick-pdf-svg</artifactId> <version>4.1.0</version></dependency>implementation 'io.github.paohaijiao:jquick-pdf-svg:4.1.0'Hello World
Section titled “Hello World”import com.github.paohaijiao.executor.JQuickPdfFactory;
import java.nio.file.Files;import java.nio.file.Paths;
public class HelloDemo {
public static void main(String[] args) throws Exception { String template = "" + "<pdf>" + " <body>" + " <h1 style=\"fontSize:24;fontColor:blue\">'Hello jquick-pdf'</h1>" + " <p>'Customer: '${customer}</p>" + " </body>" + "</pdf>";
// 绑定数据并渲染为 PDF 字节数组 / bind data and render to PDF bytes byte[] pdf = JQuickPdfFactory.create() .bind("customer", "Martin") .executeContent(template);
Files.write(Paths.get("hello.pdf"), pdf); }}三种模板来源
Section titled “三种模板来源”以下方法均返回 byte[]:
| 方法 | 模板来源 |
|---|---|
executeContent(String) |
内存中的模板文本 |
executeResource(String) |
classpath 资源,例如 "report.txt" |
executeFile(String) |
磁盘文件,例如 "D:/templates/report.txt" |
组合模板:企业信用评级报告
Section titled “组合模板:企业信用评级报告”模板从 classpath 读取,支持 flex 布局、表格、列表与内联 SVG 图表:
import com.github.paohaijiao.adaptor.JAdaptor;import com.github.paohaijiao.config.JPdfConfig;import com.github.paohaijiao.executor.JQuickPdfFactory;import com.github.paohaijiao.resouce.JReader;import com.github.paohaijiao.resouce.impl.JReSourceFileReader;
import java.io.FileOutputStream;
public class CreditReportDemo {
public static void main(String[] args) throws Exception { // 开启 flex 布局:雷达图与右侧指标面板并排显示 JPdfConfig config = new JPdfConfig(); config.getLayoutConfig().setFlexLayout(true);
JReader fileReader = new JReSourceFileReader("report.txt"); // 文档模板 JAdaptor adaptor = new JAdaptor(fileReader);
JReader svgReader = new JReSourceFileReader("radar.txt"); // 内联 SVG 图表 JAdaptor svgAdaptor = new JAdaptor(svgReader);
JQuickPdfFactory factory = new JQuickPdfFactory(config); factory.bind("svg", svgAdaptor.getRuleContent()); // 绑定 ${svg} 占位符
byte[] bytes = factory.executeContent(adaptor.getRuleContent()); try (FileOutputStream out = new FileOutputStream("credit-report.pdf")) { out.write(bytes); } }}对应的模板片段(节选自 report.txt):
<pdf> <body> <div style="textAlignment:center; marginBottom:5px; background:#3E6B9D; color:white; borderRadius:4px"> <h1 style="textAlignment:center;color:white; fontSize:20">'企业信用评级报告'</h1> <p style="textAlignment:center;color:rgba(255,255,255,0.9); fontSize:11">'报告编号: CR-2023-08975'</p> </div>
<table style="width:600px; fontSize:10"> <tr> <td style="backgroundColor:#f8f9fa;padding:5px;width:150px;">'统一信用代码'</td> <td style="backgroundColor:#f8f9fa;padding:5px;width:150px;">'91110108MA01XX1234'</td> </tr> </table>
<list style="list-style-type:none; paddingLeft:0; fontSize:11"> <li style="marginBottom:8px; padding:10px; backgroundColor:#f8f9fa; borderLeft:4px solid #4CAF50"> '营收增长率: 连续三年保持 40% 以上增长' </li> </list>
<div style="display:flex; justifyContent:space-between; marginTop:10px"> <svg style="width:400px;height:400px">${svg}</svg> <div style="width:300px"> <h3 style="fontSize:12">'评级指标说明'</h3> </div> </div> </body></pdf>生成矢量图表
Section titled “生成矢量图表”图表通过 JOption 配置,配置思路与 ECharts 一致,渲染结果是矢量图形,可直接写入 .svg 文件或嵌入文档。
import com.github.paohaijiao.axis.JCategoryAxis;import com.github.paohaijiao.axis.JValueAxis;import com.github.paohaijiao.bar.JBarChartsRenderer;import com.github.paohaijiao.code.JTrigger;import com.github.paohaijiao.series.JBar;
JOption option = new JOption();option.title().text("销售数据").subtext("2023 年度");option.tooltip().trigger(JTrigger.axis);
JCategoryAxis xAxis = new JCategoryAxis();xAxis.data("衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子");option.xAxis(xAxis);option.yAxis(new JValueAxis());
JBar bar = new JBar();bar.name("销量").data(5, 20, 36, 10, 10, 20);option.series(bar);
// 渲染为 SVG 文件,或渲染为字符串后嵌入模板JBarChartsRenderer renderer = new JBarChartsRenderer();renderer.render(option, "barchart.svg");String svg = renderer.renderToString(option);元素与样式速查
Section titled “元素与样式速查”| 元素 | 用途 |
|---|---|
<h1> … <h6> |
六级标题 |
<p> / <span> / <br> / <tab> |
段落、行内文本、换行与制表 |
<div> |
块容器:背景、边框、内边距、尺寸、旋转、flex |
<list> / <li> |
列表容器与列表项 |
<table> / <tr> / <th> / <td> |
表格与单元格样式 |
<image src="..." alt="..."> |
位图图片 |
<svg> |
矢量图,配合 ${svg} / &{svg} |
<tree> |
树形结构 |
<button> / <checkbox> / <comboBoxField> / <textArea> |
交互式表单控件 |
<areaBreak> / <htmlPageBreak> / <lineSeparator> |
强制分页 / HTML 风格分页 / 分隔线 |
<template> |
可复用模板片段 |
样式写在任意元素的 style="..." 上,minHeight(驼峰)与 min-height(标准 CSS)等价,可混用;单位支持 px(96 DPI,1px = 0.75pt)、pt、mm、cm、in;颜色支持颜色名、#RRGGBB、rgb() / rgba() 与 linear-gradient(...)。