CXF 启用 GZIP 在加载 WSDL 时失败
CXF Enabling GZIP failed at the WSDL loading
我目前在尝试为 CXF 启用 GZIP 压缩时遇到问题:WSDL 加载失败,因为它已被压缩,而客户端未对其进行解压缩。
这意味着当我执行以下操作时 :
persistenceService = Service.create(
new URL(replaceHostAndPort(
getClientServiceConfiguration().getWsMetadataPersistenceService())),
new QName("http://metadata.ws.com", "WsMetadataPersistenceService"), gzipFeature);
mDefaultMetadataPersistence = persistenceService.getPort(IWsMetadataPersistence.class);
代码在 Service.create() 上失败,因此它与配置 ClientProxy 无关。
据我在 CFX 的源代码中所知,WSDL 的加载没有使用我在参数中传递的功能,也没有使用我使用以下配置在默认总线上传递的功能:
<bean id="compressGZIPFeature" class="org.apache.cxf.transport.common.gzip.GZIPFeature"/>
<cxf:bus>
<cxf:features>
<ref bean="compressGZIPFeature"/>
</cxf:features>
</cxf:bus>
注意:我可以在使用总线元素的 CXF 内部 类 使用的总线实例中看到我的功能在那里并且被正确初始化(添加 in/out 拦截器),但是我在尝试加载 WSDL 文件时从不忽略它们。
现在我有点卡住了:难道 WSDL 一开始就不应该被 gzip 压缩吗?那是怎么回事,还是我客户端的问题?
在服务器端,我尝试了各种我能找到的组合,希望只压缩请求的内容而不是 WSDL,但无济于事:
- @GZIP
- XML总线配置
- @In/OutInterceptors
根据我对 CXF 客户端代码的理解,来自 HttpUrlConnection 的 InputStream 直接传递给 XMLReader 以读取 WSDL,而不使用拦截器(另外,GZIPInterceptor 忽略来自GET 请求所以它应该忽略 GET [...]?wsdl aniway。如果你想检查代码,请参见 WSDLManagerImpl.loadDefinition()。
我不确定它是否相关,我正在采用 adopte-openjdk 8 和 cxf 3.1.7。
我找到了解决方案:我在 HTTP 管道上添加了压缩,这甚至会使 wsdl 请求请求 GZIP 版本。问题是 WSDL reader 不处理接收到的 GZIP 流。
所以我不得不删除客户端的压缩配置并使用以下代码来确保只压缩 SOAP 请求:
public <T> T createAndConfigureService(Class<? extends T> theServiceClass, Service service){
T theWebService = service.getPort(theServiceClass);
Map<String, Object> requestHeaders = new HashMap<>();
requestHeaders.put("Accept-Encoding", new ArrayList<>(Arrays.asList("gzip")));
((BindingProvider)theWebService).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
Client client = ClientProxy.getClient(theWebService);
client.getInInterceptors().add(new GZIPInInterceptor());
return theWebService;
}
我目前在尝试为 CXF 启用 GZIP 压缩时遇到问题:WSDL 加载失败,因为它已被压缩,而客户端未对其进行解压缩。
这意味着当我执行以下操作时 :
persistenceService = Service.create(
new URL(replaceHostAndPort(
getClientServiceConfiguration().getWsMetadataPersistenceService())),
new QName("http://metadata.ws.com", "WsMetadataPersistenceService"), gzipFeature);
mDefaultMetadataPersistence = persistenceService.getPort(IWsMetadataPersistence.class);
代码在 Service.create() 上失败,因此它与配置 ClientProxy 无关。
据我在 CFX 的源代码中所知,WSDL 的加载没有使用我在参数中传递的功能,也没有使用我使用以下配置在默认总线上传递的功能:
<bean id="compressGZIPFeature" class="org.apache.cxf.transport.common.gzip.GZIPFeature"/>
<cxf:bus>
<cxf:features>
<ref bean="compressGZIPFeature"/>
</cxf:features>
</cxf:bus>
注意:我可以在使用总线元素的 CXF 内部 类 使用的总线实例中看到我的功能在那里并且被正确初始化(添加 in/out 拦截器),但是我在尝试加载 WSDL 文件时从不忽略它们。
现在我有点卡住了:难道 WSDL 一开始就不应该被 gzip 压缩吗?那是怎么回事,还是我客户端的问题?
在服务器端,我尝试了各种我能找到的组合,希望只压缩请求的内容而不是 WSDL,但无济于事:
- @GZIP
- XML总线配置
- @In/OutInterceptors
根据我对 CXF 客户端代码的理解,来自 HttpUrlConnection 的 InputStream 直接传递给 XMLReader 以读取 WSDL,而不使用拦截器(另外,GZIPInterceptor 忽略来自GET 请求所以它应该忽略 GET [...]?wsdl aniway。如果你想检查代码,请参见 WSDLManagerImpl.loadDefinition()。
我不确定它是否相关,我正在采用 adopte-openjdk 8 和 cxf 3.1.7。
我找到了解决方案:我在 HTTP 管道上添加了压缩,这甚至会使 wsdl 请求请求 GZIP 版本。问题是 WSDL reader 不处理接收到的 GZIP 流。
所以我不得不删除客户端的压缩配置并使用以下代码来确保只压缩 SOAP 请求:
public <T> T createAndConfigureService(Class<? extends T> theServiceClass, Service service){
T theWebService = service.getPort(theServiceClass);
Map<String, Object> requestHeaders = new HashMap<>();
requestHeaders.put("Accept-Encoding", new ArrayList<>(Arrays.asList("gzip")));
((BindingProvider)theWebService).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);
Client client = ClientProxy.getClient(theWebService);
client.getInInterceptors().add(new GZIPInInterceptor());
return theWebService;
}