0

我在 Netbeans 7.1.2 中使用了 Web 服务客户端向导,但是当我尝试调用其中一个方法时,我收到以下错误:

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

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

非常感谢

4

2 回答 2

5

这里有四点需要考虑。有一个请求和一个响应,还有一个客户端服务器。在谈论压缩时,重要的是要准确说明我们针对的是哪种情况。我将海报的问题读作是关于客户端的问题,因为服务器似乎已经在进行压缩。(事实上​​,它似乎要求客户端能够处理压缩)。

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

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

  • Content-encoding:如果设置了这意味着“我正在向您发送编码(例如压缩)消息”。客户端(在请求中)和服务器(在响应中)都可以使用它。

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

这两个标头元素的典型值是“gzip”,这是迄今为止 HTTP 服务器和 HTTP 客户端使用的最常见的压缩方法。还有“放气”,但坚持使用“gzip”。

让我们从头说起:从客户端到服务器的请求:

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

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

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

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 标头,您现在将看到如下内容:

内容类型:文本/xml;charset="utf-8"
接受编码:gzip
肥皂动作:“http://blahblah”
接受:text/xml、multipart/related、text/html、image/gif、image/jpeg、*;q=.2, */*; q=.2
用户代理:JAX-WS RI 2.1.5-hudson-$BUILD_NUMBER-
主机:本地主机:8084
连接:保持活动
内容长度:216

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

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

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

您的最后一个问题应该是:“我如何在我的 JAX-WS 客户端中处理压缩响应?” 或更广泛地说“我的 JAX-WS 客户端将如何处理压缩和未压缩的响应?”。好消息是,这是由 JAX-WS 透明处理的。没有什么你需要做的。JAX-WS 将自动检测到它从服务器接收到压缩响应(它只是查看响应中的 HTTP 标头)并自动为您解压缩。瞧!

所以,亲爱的发帖者,我想说的是,如果您使用的是最新版本的 JAX-WS,那么您的客户端现在已经知道如何处理压缩响应了。但是,由于客户端没有明确告诉服务器它可以理解压缩响应,因此服务器认为情况并非如此,因此会给您该错误。这是我对你所看到的猜测。

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

于 2013-04-18T10:36:10.847 回答
-1

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

         <property name="compression" value="on"/>

或者,如果您通过管理控制台管理服务器,请使用此可视指南。对于tomcat添加

         compression="on" 

到配置文件中的 tomcat<Connector/>元素。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);

作为设计问题,上述逻辑最好从 web 服务处理程序执行

于 2012-11-21T04:31:32.637 回答