[英]In a JAX-WS web service, how do I force a socket close after each Soap call is returned?
我正在使用 com.sun.httpserver.HttpServer 和 javax.xml.ws.Endpoint 發布 JAX-WS Web 服務,該服務是通過在現有 WSDL 上運行 wsimport 並實現生成的服務接口生成的。 所有這些都是 JDK 1.6 (JAX-WS RI 2.1.6) 的一部分。 我的 Web 服務作為 Java 程序運行,沒有額外的 Web 容器,應該模擬現有的 SOAP 服務,該服務是使用 Apache Axis 實現的,在 Tomcat 上運行。 現有客戶端同樣使用 Apache Axis 實現。
我遇到的問題是從客戶端到我的 JAX-WS 服務的 Soap 操作調用掛起一段時間,然后在客戶端以套接字超時結束。 即使 JAX-WS 服務立即返回 SOAP 響應,也會發生這種情況。
使用 tcpdump 和 wireshark 檢查數據包,我注意到使用現有的 Axis Web 服務,在 SOAP 響應從服務器發送到客戶端后,服務器發送一個“FIN ACK”數據包,客戶端響應“FIN ACK” ”。 與 SOAP 操作相關的所有數據包到此結束。 另一方面,當與 JAX-WS 服務一起運行時,在將 SOAP 響應發送到客戶端后,服務器不會發送“FIN ACK”。 並且客戶端似乎繼續為它讀取套接字輸入流。
這讓我相信 JAX-WS Web 服務堆棧以某種方式保持套接字打開,即使在發送了對 SOAP 調用的響應之后也是如此。 並且客戶端似乎希望套接字在 SOAP 操作結束時關閉。 不幸的是,我無法修改客戶端以使其行為有所不同。
有沒有辦法將我用來發布 JAX-WS 服務的端點或 HttpServer 實例配置為在每次 SOAP 操作后始終關閉套接字?
我嘗試將系統屬性 http.keepAlive 設置為 false,但這似乎沒有任何區別。
在此先感謝您的幫助。
我找到了解決此問題的方法,但是它不是很優雅。 本質上,在Endpoint.publish操作創建了HttpContext對象之后,我從HttpHandler對象獲得了它。 然后從我編寫的另一個HttpHandler類中調用其handle()方法,該類通過發送HttpHeader並將其“ Connection”設置為“ close”來跟進。 像這樣:
...
HttpServer server = HttpServer.create(myInetSocketAddress, 5);
HttpContext context = server.createContext(mySoapPath);
Endpoint endpoint = Endpoint.create(mySoapImpl);
endpoint.publish(context);
MyHandler handler = new MyHandler(context.getHandler());
server.removeContext(mySoapPath);
server.createContext(mySoapPath, handler);
server.start();
...
private class MyHandler implements HttpHandler {
private HttpHandler h;
public MyHandler(HttpHandler in) {
h = in;
}
public void handle(HttpExchange t) throws IOException {
h.handle(t);
t.getResponseHeaders().set("Connection", "close");
t.sendResponseHeaders(200, 0);
t.close();
}
}
它可以滿足我當前的需求,但是似乎有一種更好的方法。 如果您還有其他解決方案,請發表。 謝謝!
當我在 Java 8 中遇到這個問題時,來自 JAX-WS RI 2.2.9 的所有請求都有標頭: Connection: keep-alive
為了在每次請求后強制關閉 TCP 連接,我必須將此標頭更改為Connection: close
我是通過以下方式做到的:
SoapService service = new SoapService(url);
SoapPort port = service.getSomePort();
Map<String, List<String>> requestHeaders = new HashMap<>();
requestHeaders.put("Connection", Collections.singletonList("close"));
BindingProvider bindingProvider = (BindingProvider)port;
bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
在哪里:
public static final String HTTP_REQUEST_HEADERS = "javax.xml.ws.http.request.headers";
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.