JAX-WS Netbeans如何启用压缩Web服务客户端

时间:2012-11-19 22:38:26

标签: web-services netbeans compression jax-ws

我在Netbeans 7.1.2中使用了Web Service Client向导,但是当我尝试调用一个方法时,我收到以下错误:

javax.xml.ws.soap.SOAPFaultException:异常:压缩未启用,此Web服务期望客户端支持GZIP,Deflate Compression

生成的骨架文件很多,我无法弄清楚如何启用压缩。任何人都可以建议吗?

非常感谢

2 个答案:

答案 0 :(得分:4)

这里有四件事需要考虑。有请求响应,还有客户端服务器。在谈论压缩时,准确确定我们针对哪些案例非常重要。我把海报的问题看作是关于客户端的事情,因为看起来服务器已经在进行压缩。 (实际上它似乎要求客户端能够处理压缩)。

这里有一点背景:压缩提示是HTTP协议的标准部分。客户端将通过向请求发送适当的HTTP头来向服务器指示它愿意接受压缩响应。同样,服务器将指示它是否已通过响应中的适当HTTP头元素发送了压缩响应。客户端也可以发送压缩请求。

这些是相关的HTTP标头元素:

  • Content-encoding:如果设置此项,则表示“我正在向您发送已编码(例如压缩)的消息”。客户端都可以使用它(在请求中)以及服务器(在响应上)。

  • Accept-encoding:如果设置了这意味着“我可以理解这些类型的编码(例如压缩方法),所以请随时向我发送以该格式编码的数据”。

这两个头元素的典型值是“gzip”,它是HTTP服务器和HTTP客户端使用的最常用的压缩方法。还有“deflate”但坚持使用“gzip”。

让我们从头开始:从客户端到服务器的请求。:

实际上很难看到这种压缩。原因是客户端无法预先知道服务器是否可以理解压缩请求。因此,通常最好不要尝试这一点。通常这不是问题,因为它通常是很大的响应。如果绝对有必要压缩请求,那么您需要首先以某种方式查询服务器的功能,或者绝对确定它可以处理压缩请求。

然后是更有趣的部分:从服务器到客户端的响应

首先,客户端需要告诉服务器他愿意接受压缩响应。这是根据请求完成的(呃!)。在Metro指南here中解释了如何将HTTP标头元素添加到JAX-WS出站请求的一般方法。所以你会这样做:

SomeWebService someWS = service.getMyWebServicePort();
((BindingProvider)someWS).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
    Collections.singletonMap("Accept-Encoding",Collections.singletonList("gzip")));

您可能会说:“这不会取代所有的HTTP标头元素并将其替换为单个元素标头吗?”。技术上是正确的,但此时JAX-WS尚未添加任何HTTP标头。 JAX-WS稍后会添加自己的头元素。如果您监视服务器收到的HTTP标头,您现在将看到如下内容:

content-type : text/xml;charset="utf-8"
accept-encoding : gzip
soapaction : "http://blahblah"
accept : text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
user-agent : JAX-WS RI 2.1.5-hudson-$BUILD_NUMBER-
host : localhost:8084
connection : keep-alive
content-length : 216

如果没有我们明确的行动,“accept-encoding”元素就不会存在。 (好问题为什么JAX-WS默认不添加它?)

现在你完成了客户端。上一张海报解释了如何在服务器端添加压缩功能。需要注意的是,服务器端的压缩(只要我们谈论压缩响应)仅由容器处理,例如:由Tomcat,Glassfish,JBoss等,而不是您的代码。您只需要在容器的配置中翻转一个开关。

几乎完成了。服务器现在可以自由地向客户端发送gzip压缩响应,但服务器可以自行决定。服务器可以做或不做。你不知道这个。

您的最后一个问题应该是:“我的JAX-WS客户端如何处理压缩响应?”或者更广泛地说“我的JAX-WS客户端将如何应对压缩与未压缩的响应?”。好消息是JAX-WS透明地处理了这个问题。你无需做任何事情。 JAX-WS将自动检测到它从服务器接收到压缩响应(它只是查看响应中的HTTP头),它会自动为您解压缩。瞧!

所以,亲爱的海报,我想最有可能的是,如果您使用的是最新版本的JAX-WS,您的客户端现在已经可以处理压缩响应了。但是,由于客户端没有明确告诉服务器它可以理解压缩响应,因此服务器认为不是这种情况,因此会给出错误。这是我对你所看到的猜测。

哦,还有一件事。根据RFC 2616,HTTP标头元素名称(它们被称为“标题字段”)不区分大小写。因此,您可以在不同的帖子中看到这种拼写有很多不同的方式。

答案 1 :(得分:-1)

您可以从应用程序服务器配置中更好地启用压缩。从你的问题来看,你最有可能使用glassfish或tomcat(我更像是一个tomcat人)。对于glassfish,您可以通过将以下内容添加到domain.xml

来启用压缩
         <property name="compression" value="on"/>

或者如果您通过管理控制台管理服务器,请使用this visual guide。对于tomcat add

         compression="on" 

<Connector/>配置文件中的tomcat server.xml元素。

要实际发送压缩的JAX-WS请求,只需通过将压缩标头添加到HTTP有效负载来指示您发送压缩请求的意图

    Map<String, List<String> theHeaders = new HashMap<String, List<String>>();
theHeaders.put("Content-Encoding", Collections.singletonList("gzip"));//this indicates you're sending a compressed request
theHeaders.put("Accept-Encoding", Collections.singletonList("gzip")); //this says you're willing to accept a compressed response
Map<String, Object> reqContext = ((bindingProvider) proxy)
        .getRequestContext(); //get access to the request context of your webservice request
requestContext.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);

作为设计问题,上述逻辑最好从网络服务handler执行