简体   繁体   English

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

[英]JAX-WS Netbeans how to enable compression web service client

I used the Web Service Client wizard in Netbeans 7.1.2, however when I try to call one the methods i receive the following error: 我在Netbeans 7.1.2中使用了Web服务客户端向导,但是当我尝试调用一种方法时,我收到以下错误:

javax.xml.ws.soap.SOAPFaultException: Exception: Compression is Not Enabled,This Web Service expects clients to support GZIP,Deflate Compression javax.xml.ws.soap.SOAPFaultException:异常:压缩未启用,此Web服务期望客户端支持GZIP,延迟压缩

The generated skeleton files are numerous and I am unable to work out how to enable compression. 生成的框架文件很多,我无法确定如何启用压缩。 Can anyone please advise? 任何人都可以请教吗?

Many thanks 非常感谢

There are four things to consider here. 这里有四件事要考虑。 There's a request and a response and there's a client and server . 有一个请求和一个响应 ,有一个客户端服务器 When talking about compression it is important to be precise as to which of these cases we are targeting. 在讨论压缩时,准确确定我们要针对的是哪种情况很重要。 I read the poster's question as being about the client side of things as it seems the server is already doing compression. 我读到发布者的问题是关于客户端的问题,因为服务器似乎已经在进行压缩。 (in fact it seems it mandates the client to be able to handle compression). (实际上,它似乎要求客户端能够处理压缩)。

Here's a little background: Compression hints is a standard part of the HTTP protocol. 这里有一些背景知识:压缩提示是HTTP协议的标准部分。 The client will indicate to the server that it is willing to accept a compressed response by sending appropriate HTTP headers with the request. 客户端将通过与请求一起发送适当的HTTP标头,向服务器指示它愿意接受压缩的响应。 Equally the server will indicate if it has sent a compressed response by an appropriate HTTP header element in the response. 同样,服务器将通过响应中的适当HTTP标头元素来指示它是否发送了压缩响应。 The client can also send a compressed request. 客户端还可以发送压缩的请求。

These are the relevant HTTP headers elements: 这些是相关的HTTP标头元素:

  • Content-encoding : If this is set it means "I'm sending you an encoded (eg compressed) message". Content-encoding :如果设置,则表示“我正在向您发送编码(例如压缩)消息”。 Both the client can use this (on the request) and well as the server (on the response). 客户端(在请求上)和服务器(在响应上)都可以使用它。

  • Accept-encoding : If this is set it means "I can understand these types of encodings (eg compression methods), so feel free to send me data which is encoded in that format". Accept-encoding :如果设置,则表示“我可以理解这些类型的编码(例如压缩方法),所以请随时向我发送以该格式编码的数据”。

The typical value of these two header elements are "gzip" which is by far the most common compression method used by HTTP servers and HTTP clients. 这两个标头元素的典型值是“ gzip”,这是迄今为止HTTP服务器和HTTP客户端使用的最常见的压缩方法。 There's also "deflate" but stick with "gzip". 还有“放气”,但坚持使用“ gzip”。

Let's start from the beginning: The request from the client to the server.: 让我们从头开始:从客户端到服务器的请求

It is actually quite rare to see this compressed. 实际上很少看到这种压缩。 The reason is that the client cannot know in advance if the server can understand a compressed request. 原因是客户端无法提前知道服务器是否可以理解压缩的请求。 So it is generally best not to attempt this. 因此,通常最好不要尝试此操作。 Typically this is not a problem as it is most often the response that is big. 通常,这不是问题,因为响应通常很大。 If it is absolutely necessary to compress the request then you would need to first somehow query the server for its capabilities or be absolutely sure that it can handle a compressed request. 如果绝对有必要压缩请求,那么您首先需要以某种方式查询服务器的功能,或者绝对确保它可以处理压缩的请求。

Then to the more interesting part: the response from the server to the client. 接下来是更有趣的部分:从服务器到客户端的响应

First of all the client needs to tell the server that he's willing to accept a compressed response. 首先,客户端需要告诉服务器他愿意接受压缩的响应。 This is done on the request (duh!). 这是根据请求完成的(duh!)。 The general method of how to add a HTTP header element to a JAX-WS outbound request is explained in the Metro guide here . Metro指南在此处说明了如何向JAX-WS出站请求添加HTTP标头元素的一般方法。 So you would do like this: 所以你会这样:

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

You might say: "Won't this replace all of the HTTP header elements and replace it with a single element header?". 您可能会说:“这是否将替换所有 HTTP标头元素并将其替换为单个元素标头?”。 Technically true but at this point JAX-WS hasn't yet added any HTTP header. 从技术上讲是正确的,但是此时JAX-WS尚未添加任何HTTP标头。 JAX-WS will add its own header elements later. JAX-WS稍后将添加其自己的标头元素。 If you monitor the HTTP header that the server receives you'll now see something like this: 现在,如果监视服务器接收的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

The "accept-encoding" element wouldn't have been there without our explicit action. 如果没有我们的明确行动,“ accept-encoding”元素就不会存在。 (good question why JAX-WS doesn't add this by default ??) (很好的问题,为什么JAX-WS默认不添加它??)

Now you're done with the client side. 现在您已经完成了客​​户端。 The previous poster has explained how to add compression ability on the server-side. 上一个海报说明了如何在服务器端添加压缩功能。 What is relevant to note is that compression on the server-side (as long as we talk about compressing the response ) is handled solely by the container, eg by Tomcat, Glassfish, JBoss, etc, and not by your code. 需要注意的是,服务器端的压缩(只要我们谈论压缩响应 )仅由容器(例如Tomcat,Glassfish,JBoss等)处理,而不是由代码处理。 You just need to flip a switch in the container's configuration. 您只需要在容器的配置中翻转一个开关即可。

Almost done. 快完成了 The server is now free to send your client a gzip compressed response but at the sole discretion of the server. 现在,服务器可以自由地向您的客户端发送gzip压缩的响应,但由服务器自行决定。 The server may do it or not. 服务器可以执行或不执行。 You don't know this. 你不知道

Your final question should be: "How do I in my JAX-WS client handle a compressed response?" 您的最后一个问题应该是:“我如何在我的JAX-WS客户端中处理压缩的响应?” or more broadly "how would my JAX-WS client cope with compressed vs uncompressed responses?". 或更广泛地说,“我的JAX-WS客户端将如何处理压缩响应与未压缩响应?”。 The good news is that this is handled transparently by JAX-WS. 好消息是,这是由JAX-WS透明处理的。 There's nothing you need to do. 您什么都不需要做。 JAX-WS will automatically detect that it receives a compressed response from the server (it simply looks at the HTTP headers in the response) and it will automatically decompress it for you. JAX-WS将自动检测到它从服务器接收到压缩的响应(它只是查看响应中的HTTP标头),并将自动为您解压缩。 Voila! 瞧!

So, dear poster, I would say that most likely, if you are using a recent version of JAX-WS, your client will already now how to handle a compressed response. 因此,亲爱的发布者,我想说,很可能,如果您使用的是最新版本的JAX-WS,那么您的客户端现在已经将如何处理压缩响应。 However since the client hasn't explicitly told the server that it can understand a compressed response the server assumes this not to be the case and hence gives you that error. 但是,由于客户端尚未明确告知服务器它可以理解压缩的响应,因此服务器认为情况并非如此,因此会给您该错误。 That is my guess to what you are seeing. 那是我对您所看到的猜测。

Ohh, and one more thing. 哦,还有一件事。 HTTP Header element names (they are rightfully called "header fields") are case-insensitive as per RFC 2616. So you see this spelled in lots of different ways in different postings. 根据RFC 2616,HTTP标头元素名称(它们正确地称为“标头字段”)不区分大小写。因此,您会在不同的帖子中看到许多不同的拼写方式。

You can enable compression better from the application server configuration. 您可以从应用程序服务器配置中更好地启用压缩。 From your question, you're most likely using glassfish or tomcat(I'm more of a tomcat person). 从您的问题来看,您最有可能使用玻璃鱼或雄猫(我更像是雄猫人)。 For glassfish, you can enable compression by adding the following to your domain.xml 对于玻璃鱼,可以通过将以下内容添加到domain.xml来启用压缩

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

Or if you're managing your server via the admin console, use this visual guide . 或者,如果您要通过管理控制台管理服务器,请使用此直观指南 For tomcat add 对于tomcat添加

         compression="on" 

to your tomcat <Connector/> element in the server.xml config file. server.xml配置文件中的tomcat <Connector/>元素。

To actually send a compressed JAX-WS request, simply indicate your intention to send a compressed request by adding the compression header to your HTTP payload 要实际发送压缩的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);

The above logic is better performed from a webservice handler as a matter of design 通过设计,可以从Web服务处理程序更好地执行上述逻辑

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM