9

私はサーバークライアントアーキテクチャを使用しており、クライアントはXMLをサーバーに送信します。サーバーは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を明示的にオーバーライドしたくない場合は、Apachecommons -ioがこれを実現する実装を提供します。

を見てみましょう :

CloseShieldInputStream

于 2012-08-27T17:24:24.837 に答える