Java Servlet项目中如何实现数据库表格内容的PDF/CSV下载功能
功能实现步骤
1 前端新增下载入口
你现有的Servlet默认输出HTML表格,先在原有表格下方添加下载按钮,直接在你当前输出</table>的代码后追加以下内容即可:
out.println("<div style='margin: 15px 0;'>"); out.println("<a href='/BookingHistorikk?type=csv' style='padding: 6px 12px; background: #2ecc71; color: #fff; text-decoration: none; margin-right: 10px; border-radius: 4px;'>导出CSV</a>"); out.println("<a href='/BookingHistorikk?type=pdf' style='padding: 6px 12px; background: #3498db; color: #fff; text-decoration: none; border-radius: 4px;'>导出PDF</a>"); out.println("</div>");
2 按请求类型分支处理逻辑
修改doGet方法,先获取请求参数type,判断是返回页面还是导出文件,把你原有输出HTML的逻辑包在无type参数的分支里:
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { String exportType = req.getParameter("type"); // 无导出参数时走原有HTML页面逻辑 if (exportType == null) { // 你原来的输出HTML表格的全部代码放在这里 return; } // 处理导出逻辑 Connection con = null; try { Class.forName("org.mariadb.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mariadb:**********", "root", "pass"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("select * from BOOKING"); if ("csv".equals(exportType)) { // CSV导出逻辑,无需额外依赖 res.setContentType("text/csv;charset=UTF-8"); res.setHeader("Content-Disposition", "attachment; filename=booking_record.csv"); // 解决Windows Excel打开乱码问题,加BOM头 res.getWriter().write('\ufeff'); PrintWriter csvWriter = res.getWriter(); // 写表头 csvWriter.println("Start Dato,Slutt Dato,Kommentar,Levert,Total Pris"); // 写内容 while (rs.next()) { String cmnt = rs.getString("Cmnt") == null ? "" : rs.getString("Cmnt"); // 处理内容里的逗号、引号避免CSV格式错误 if (cmnt.contains(",") || cmnt.contains("\"")) { cmnt = "\"" + cmnt.replace("\"", "\"\"") + "\""; } csvWriter.println(String.join(",", rs.getDate("StartDate").toString(), rs.getDate("EndDate").toString(), cmnt, rs.getBoolean("IsDelivered").toString(), String.valueOf(rs.getInt("TotalPrice")) )); } csvWriter.flush(); } else if ("pdf".equals(exportType)) { // PDF导出逻辑,需引入OpenPDF依赖 res.setContentType("application/pdf"); res.setHeader("Content-Disposition", "attachment; filename=booking_record.pdf"); Document document = new Document(); PdfWriter.getInstance(document, res.getOutputStream()); document.open(); // 生成5列的PDF表格 PdfPTable pdfTable = new PdfPTable(5); // 写表头 pdfTable.addCell("Start Dato"); pdfTable.addCell("Slutt Dato"); pdfTable.addCell("Kommentar"); pdfTable.addCell("Levert"); pdfTable.addCell("Total Pris"); // 写内容 while (rs.next()) { pdfTable.addCell(rs.getDate("StartDate").toString()); pdfTable.addCell(rs.getDate("EndDate").toString()); pdfTable.addCell(rs.getString("Cmnt") == null ? "" : rs.getString("Cmnt")); pdfTable.addCell(rs.getBoolean("IsDelivered") ? "是" : "否"); pdfTable.addCell(String.valueOf(rs.getInt("TotalPrice"))); } document.add(pdfTable); document.close(); } } catch (Exception e) { res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "导出失败:" + e.getMessage()); } finally { // 确保数据库连接释放 if (con != null) { try { con.close(); } catch (SQLException ignored) {} } } }
3 PDF导出依赖配置
如果是Maven项目,直接在pom.xml里添加OpenPDF依赖即可:
<dependency> <groupId>com.github.librepdf</groupId> <artifactId>openpdf</artifactId> <version>1.3.30</version> </dependency>
如果是普通Web项目,下载对应jar包放到WEB-INF/lib目录下即可。
优化建议
可以把查询BOOKING表的逻辑抽成单独的公共方法,避免HTML渲染、CSV导出、PDF导出三个场景重复写数据库查询代码,后续修改字段也只需要改一次。
内容的提问来源于stack exchange,提问作者oroezz
相关产品推荐
相关产品推荐

