iText 7 添加文字水印需在onStartPage中用PdfCanvas绘制到底层canvas,而非document.add;表格列宽须先设table.setWidth(UnitValue.createPercentValue(100));中文需注册simhei.ttf等字体;大数据量时应flush()并避免Document复用。

用 iText 7 添加文字水印为什么总被内容盖住?
水印显示不出来,或者只在第一页、位置偏移,本质是图层顺序和绘制时机没控制好。iText 中水印必须在 onStartPage 里用 canvas 绘制,且要调用 showTextAligned 在底层 canvas(getPdfDocument().getPageSize().getLeft(), ... 这类绝对坐标)上画,而不是往 Document 内容流里加。
- 别在
document.add()里塞水印文本——那是内容层,必然压在水印上 - 务必用
PdfCanvas操作当前页的底层 canvas:new PdfCanvas(page.getPdfObject(), document.getPdfDocument()) - 字体大小建议设为
60f以上,透明度用setFillColor(new DeviceRgb(200, 200, 200))控制,太淡会被忽略 - 旋转角度用
showTextAligned(..., TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45),别依赖默认方向
iText 7 表格(Table)列宽不生效的常见原因
Table 的列宽行为和 HTML 表格完全不同:它默认按内容自适应,setWidthPercentages() 不是“设置百分比宽度”,而是“按比例分配剩余可用宽度”。如果你没显式设表宽或容器约束,百分比就失去参照。
- 必须先调用
table.setWidth(UnitValue.createPercentValue(100)),否则setWidthPercentages(new float[]{2, 1, 1})无效 - 列宽数组长度必须等于列数,多一个少一个都会抛
IllegalArgumentException - 避免在表格内嵌套
Cell时用setPadding(0)过度压缩——边框和内边距会影响视觉列宽感知 - 导出到 A4 页面时,总宽别超
595f(点单位),否则自动换行或截断,看起来像“列宽失效”
生成 PDF 后中文乱码或方块字?检查字体注册这一步
iText 7 默认不支持中文字体,Document 初始化时没指定字体,所有中文都会 fallback 到 Helvetica,结果就是方块。不是编码问题,是字体缺失。
- 必须用
PdfFontFactory.createFont("simhei.ttf", PdfEncodings.IDENTITY_H, true)加载本地字体文件(注意路径是 classpath 或绝对路径) - 创建
FontProvider并注册进Document:document.setFontProvider(fontProvider),不能只传给单个Paragraph - 别用系统字体名如
"SimHei"——iText 不识别 Windows 字体名,只认文件路径或已注册的PdfFont实例 - 如果用 OpenJDK 17+,确保
simhei.ttf文件未被系统策略拦截(某些 Docker 环境会静默拒绝读取)
PDF 导出慢、内存暴涨?警惕 Document 和 PdfWriter 的生命周期
大报表(比如万行数据)下,反复 document.add(table) 不会立即写磁盘,而是一直缓存在内存里,直到 document.close() 才 flush。中间没做分页或流式写入,很容易 OOM。
- 每添加完一个逻辑区块(如每 100 行),手动调用
document.flush()强制写入缓冲区 - 不要复用同一个
Document对象跨请求——Spring Bean 默认单例,会导致并发写冲突或残留状态 - 用
new PdfWriter(new FileOutputStream(path), new WriterProperties().setLinearization(true))开启线性化(fast web view),能显著改善浏览器首次加载体验 - 关闭日志输出:
Logger.getLogger("com.itextpdf.kernel.pdf.PdfDocument").setLevel(Level.OFF),大量 INFO 日志也会拖慢速度
水印叠加、表格尺寸、中文字体、内存管理——这四点卡住 90% 的实际项目。尤其要注意 PdfCanvas 和 Document 是两套绘制体系,混用就白忙活。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











