Java中使用PDFBox生成含SQL查询的PDF时抛出异常问题
排查PDFBox生成PDF时的异常问题
先从你给出的两段代码里,梳理几个大概率导致执行期异常的点:
1. 字符串数组拼接方法append的潜在问题
- 空数组/Null判断缺失:如果传入的
a或b是null,调用a.length或b.length会直接抛出NullPointerException。比如当SQL查询没有返回结果,或者其中一个拼接数组为空时就会触发。 - 子数组长度不一致风险:如果
a和b的子数组(也就是每行数据)列数不一样,后续drawTable里取content[0].length作为总列数,会导致表格列数和实际数据不匹配,轻则内容错位,重则抛出数组越界异常。
修改后的append方法可以加上防护:
public static String[][] append(String[][] a, String[][] b){ // 处理null情况,把null当作空数组 String[][] safeA = (a == null) ? new String[0][] : a; String[][] safeB = (b == null) ? new String[0][] : b; // 检查列数是否一致 if (safeA.length > 0 && safeB.length > 0) { int colsA = safeA[0].length; int colsB = safeB[0].length; if (colsA != colsB) { throw new IllegalArgumentException("两个数组的列数必须一致"); } } String[][] result = new String[safeA.length + safeB.length][]; System.arraycopy(safeA, 0, result, 0, safeA.length); System.arraycopy(safeB, 0, result, safeA.length, safeB.length); return result; }
2. 表格绘制方法drawTable的潜在问题
- 空数据判断缺失:如果
content是空数组(比如SQL查询无结果),content[0].length会抛出ArrayIndexOutOfBoundsException。必须先判断rows > 0再处理列数。 - 文本添加环节的隐藏问题:你代码里“添加字符串内容”的部分没贴出来,但这是高频异常点:
- 有没有提前设置字体?如果没调用
contentStream.setFont(PDType1Font.HELVETICA, 12)这类方法,添加文本时会抛出异常。 - 文本坐标计算是否正确?比如每个单元格的文本应该从
margin + cellMargin,nexty + cellMargin的位置开始,而且要注意beginText()和endText()的包裹,否则会有状态异常。
- 有没有提前设置字体?如果没调用
- 页面边界检查:如果传入的
y值太小,导致y - tableHeight小于页面底部(一般是0),虽然不会直接抛异常,但可能导致内容被截断,甚至部分绘制操作触发坐标异常。
修改后的drawTable开头加上空数据防护,同时补全文本添加的示例:
public static void drawTable(PDPage page, PDPageContentStream contentStream, float y, float margin, String[][] content) throws IOException{ final int rows = content.length; // 空数据直接返回,避免异常 if (rows == 0) { return; } final int cols = content[0].length; final float rowHeight = 20.0f; final float tableWidth = page.getMediaBox().getWidth() - (2.0f * margin); final float tableHeight = rowHeight * (float)rows; final float colWidth = tableWidth / (float)cols; final float cellMargin = 2f; // 设置字体(必须先设置,否则添加文本会抛异常) contentStream.setFont(PDType1Font.HELVETICA, 12); // 绘制行 float nexty = y; for(int i=0;i<=rows;i++){ contentStream.moveTo(margin, nexty); contentStream.lineTo(margin + tableWidth, nexty); contentStream.stroke(); nexty -= rowHeight; } // 绘制列 float nextx = margin; for(int i=0;i<=cols;i++){ contentStream.moveTo(nextx, y); contentStream.lineTo(nextx, y - tableHeight); contentStream.stroke(); nextx += colWidth; } // 添加字符串内容 contentStream.beginText(); float textY = y - rowHeight + cellMargin; for(int i=0; i<rows; i++){ float textX = margin + cellMargin; for(int j=0; j<cols; j++){ contentStream.newLineAtOffset(textX, textY); contentStream.showText(content[i][j] != null ? content[i][j] : ""); // 重置文本位置,避免累加偏移 contentStream.newLineAtOffset(-textX, -textY); textX += colWidth; } textY -= rowHeight; } contentStream.endText(); }
额外排查建议
如果修改后还是抛异常,建议:
- 打印出完整的异常栈信息,这是定位问题的关键(比如是NPE、IO异常还是PDFBox的特定异常)。
- 检查SQL查询结果转成二维数组的过程,有没有出现
null的行或列,或者数据类型转换错误。
内容的提问来源于stack exchange,提问作者Shirwyn
相关产品推荐
相关产品推荐

