在首先生成的 iframe 中生成预览页面后,servlet 生成 PDF 文档。这通常有效,看起来像这样:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if ("directPrintDocumentDoIt".equals(request.getParameter("method"))) {
generatePDF(request, response);
}
if ("directPrintDocumentWaiting".equals(request.getParameter("method"))) {
String queryString = request.getQueryString().replace("directPrintDocumentWaiting", "directPrintDocumentDoIt");
renderWaiting(request, response, queryString);
}
if ("directPrintDocument".equals(request.getParameter("method"))) {
String queryString = request.getQueryString().replace("directPrintDocument", "directPrintDocumentWaiting");
renderIFrameWaiting(request, response, queryString);
}
}
首先,调用“directPrintDocument”和方法“renderIFrameWaiting”,生成 iframe 页面并将内容写入 servlet 响应(iframe src 调用 doPost 的下一部分。我确信这不会产生错误,所以我省略了这个代码片段)。然后调用“directPrintDocumentWaiting”和“renderWaiting”方法,在之前生成的 iframe 页面中生成预览页面,而生成的 javascript 调用“directPrintDocumentDoIt”最终生成 PDF:
private void renderWaiting(HttpServletRequest request, HttpServletResponse response, String queryString) throws IOException {
StringBuffer output = new StringBuffer();
response.setContentType("text/html; charset=ISO-8859-1");
response.setHeader("Cache-Control", "no-cache");
output.append("<html>\n");
output.append("<head>\n");
output.append("<meta http-equiv='Content-Type' content='text/html;charset=iso-8859-1'>\n");
output.append("<meta http-equiv='expires' content='0'>\n");
output.append("<meta http-equiv='cache-control' content='no-cache'>\n");
output.append("<meta http-equiv='pragma' content='no-cache'>\n");
output.append("</head>\n");
output.append("<script type=\"text/javascript\">\n");
output.append("function formSubmit() {\n");
output.append("document.forms[0].target=\'_self\';\n");
output.append("document.body.style.cursor = \"wait\";\n");
output.append("var formAction = document.forms[0].action;\n");
output.append("document.forms[0].submit();\n");
output.append("}\n");
output.append("</script>\n");
output.append("<body onload=\"self.focus(); formSubmit();\">\n");
output.append("<form name=\"druckenForm\" method=\"post\" action=\"" + request.getRequestURI() + "?" + queryString + "\" onsubmit=\"return false;\">\n");
output.append("<p align=\"center\" valign=\"center\">Druck wird erzeugt...\n</p>\n");
output.append("<p align=\"center\" valign=\"center\">Der erstmalige Start kann etwas länger dauern.</p>\n");
output.append("</form>\n");
output.append("</body>\n");
output.append("</html>");
response.setContentLength(output.length());
response.getOutputStream().write(output.toString().getBytes());
response.getOutputStream().flush();
response.getOutputStream().close();
}
这通常有效,但有时会发生一些奇怪的事情。不知何故,最后一次调用“directPrintDocumentDoIt”将被调用两次,因此 generatePDF 也将被调用两次,整个打印输出陷入困境(在大多数情况下,PDF 将被白页覆盖)。这种情况发生的概率为 50 次中的 1 次,因此几乎无法重现。首先我想到了一些线程问题,所以我在每次调用时记录了线程 ID:
log.info("> current thread:" + Thread.currentThread().getId());
线程 id 总是相同的,所以我怀疑这真的是线程问题。令我困惑的是,当发生此错误时,提琴手在执行 javascript POST 调用后记录了第 4 次调用。通常有 3 次调用(“directPrintDocument”、“directPrintDocumentWaiting”和“directPrintDocumentDoIt”)。当有 4 次调用时,它总是以相同的方式发生:“directPrintDocumentDoIt”将被调用两次(与 POST 请求相同的 URL)但突然作为 GET 请求。我不知道这个 GET 请求来自哪里(在“generatePDF”中没有其他请求调用)。因此,要么是 javascript 产生了一些奇怪的行为(但为什么很少发生),要么是 web 容器(Websphere)产生了一些我不明白的奇怪的东西。有趣的是,提琴手在第 3 次和第 4 次调用时显示了不同的实体大小。正确的 POST 调用的实体大小为 84.138 字节。第 4 次调用(错误的)有 83.883 个字节。我不知道这意味着什么,但也许这些信息会有所帮助。我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?我感觉这个错误在我重新启动或发布到 Websphere 后更频繁地发生。在这种情况下,它会在第一次尝试时发生(但并非总是如此)。这不可能是巧合。有什么想法吗?