我在 tomcat 中部署了一个 jaxws web 服务,当它只为一个请求提供服务时它恰好运行良好,但是当有两个同时请求时创建 PDF 的过程失败并出现错误 “文档未打开” itext jar 包含在 webservice war 中,所以我们认为这不是类加载问题。 什么可能会失败?
编辑最初作为答案提供的代码:
public Boolean PDF(BeanGeneral general2, String carpeta) {
general = general2;
document = new Document();
document.setPageSize(PageSize.LETTER);
try {
fileName = carpeta + "/" + general.getNoSAP() + ".pdf";
writer = PdfWriter.getInstance(document, new FileOutputStream(fileName));
document.open();
cb = writer.getDirectContent();
PdfReader reader = null;
reader = new PdfReader(general.getParametros().getProperty("images") + "/template.pdf");
page = writer.getImportedPage(reader, 1);
document.newPage();
cb.addTemplate(page, 0, 0);
getHeader();
getDetalle();
getFooter();
document.close();
file = new File(fileName);
} catch (IllegalPdfSyntaxException e) {
error = false;
return error;
} catch (Exception e) {
e.printStackTrace();
error=false;
return error;
}
return error;
}
最佳答案
您的附加信息(不幸的是,您将其作为答案给出,而不是对问题的编辑)表明变量 document
、writer
和 cb
(可能更多)实际上不是方法变量,而是类实例的成员。
在同时请求期间,两个请求都使用此类实例。因此,两个请求都将它们的 Document
、PdfWriter
和 PdfContentByte
放入相同的变量中。
这意味着请求的值稍微落后于 win 并且两个请求都使用后面请求的值工作。这反过来意味着:
- 获胜的文档检索从覆盖变量内容开始的两个请求过程中生成的所有内容;还有那个
- 即使在第一个请求关闭后,获胜的文档仍被后面的请求使用:这会导致您观察到的“文档未打开”错误。
(实际上这是一种简化;因为您没有引入内存同步障碍,变量可能会缓冲在不同的缓冲区中,并且这些缓冲区的同步可能会在任何随机时间发生...)
您可以通过多种不同的方式解决此问题:
将您的方法
PDF
声明为synchronized
;由于成员变量的值只需要在此方法运行期间保持不变,这就足够了:public synchronized Boolean PDF(BeanGeneral general2, String carpeta)
或
将这些成员变量转换为方法变量,并在需要时将它们作为参数添加到方法
getHeader
、getDetalle
和getFooter
中那里;或者将这些成员变量转化为
ThreadLocal
变量。
关于multithreading - itext "The document is not open"部署在 tomcat 7 中的 webservice 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28866970/