9

我有一个服务器-客户端架构,其中客户端将 XML 发送到服务器,服务器读取它并从中生成 PDF 并将其发送回客户端。

在客户端:

JAXBElement<Xml> xml = ...
Socket sock = ...
Marshaller marshaller = ...
marshaller.marshal(xml, sock.getOutputStream());
sock.shutdownOuput();    

同时在服务器端:

ServerSocket server = ...
Socket client = server.accept();
Unmarshaller unmarshaller = ...
// client.isClosed() -> false
JAXBElement<Xml> xml =
  (JAXBElement<Xml>)) unmarshaller.unmarshall(client.getInputStream());
// client.isClosed() -> true
Pdf pdf = new Pdf(xml);
client.getOutputStream().write(pdf.toBytes());
// "socket is closed" IOException is thrown

如果我不解组客户端InputStream(在服务器端)并且只是发回一个虚拟 PDF,那么一切都会顺利进行。所以,我必须假设Unmarshaller关闭InputStream它是给定的,因此隐含地关闭客户Socket毁了我的一天......

关于解决这个问题的任何想法?

4

2 回答 2

10

XMLEntityManager 类在 InputStream 上调用 close。

您可以使用FilterInputStream来避免对底层流的 close() 调用。

子类 FilterInputStream 并用空主体覆盖 close() 方法:

public class MyInputStream extends FilterInputStream {
  public MyInputStream(InputStream in) {
    super(in);
  }

  @Override 
  public void close() {
    // do nothing
  }
}

然后将您的 unmarshall() 调用更改为

JAXBElement<Xml> xml =
    (JAXBElement<Xml>)) unmarshaller.unmarshall(new MyInputStream(client.getInputStream()));

因此,JAXB 框架仍然在流上调用 close(),但它现在被您自己的流实例过滤掉,并且套接字流保持打开状态。

于 2011-07-23T11:19:59.737 回答
7

如果您不想像 vanje 建议的那样在您的代码中显式覆盖 InputStream,Apache commons-io提供了一个实现这一点的实现:

看一眼 :

CloseShieldInputStream

于 2012-08-27T17:24:24.837 回答