基于ONVIF WSDL的JAX-WS客户端与服务端SOAP版本不兼容问题
使用JAX-WS基于ONVIF WSDL生成Java客户端与服务端后,出现客户端默认采用SOAP 1.2(HTTP Content-Type为application/soap+xml),但服务端仅暴露SOAP 1.1(HTTP Content-Type为text/xml)的不对称情况,导致双方抛出Unsupported Content-Type异常。经curl验证:发送text/xml请求可成功,发送application/soap+xml则返回415错误。环境为Ubuntu 22.04、OpenJDK 11、嵌入式Jetty 10/11、Maven JAX-WS Plugin 2.3.5/3.0.2,测试Java EE与Jakarta EE工具集均出现此问题,且ONVIF WSDL无法修改。
1. 能否修改客户端使其始终使用SOAP 1.1请求?
可以,有两种可行方案:
方案一:生成客户端时通过绑定文件强制指定SOAP 1.1
创建自定义绑定文件(如soap11-binding.xml),覆盖WSDL中的SOAP绑定配置:
<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" wsdlLocation="path/to/your/onvif.wsdl"> <jaxws:bindings node="wsdl:definitions"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> </jaxws:bindings> </jaxws:bindings>
在Maven JAX-WS Plugin中引入该绑定文件:
<plugin> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>2.3.5</version> <executions> <execution> <goals> <goal>wsimport</goal> </goals> <configuration> <wsdlFiles> <wsdlFile>src/main/resources/onvif.wsdl</wsdlFile> </wsdlFiles> <bindingFiles> <bindingFile>src/main/resources/soap11-binding.xml</bindingFile> </bindingFiles> </configuration> </execution> </executions> </plugin>
方案二:在已生成的客户端代码中强制指定SOAP 1.1绑定
创建Port实例时,显式指定SOAP 1.1协议:
// 初始化Service YourOnvifService service = new YourOnvifService(); // 创建Port时指定SOAP 1.1绑定 YourOnvifPort port = service.getPort( new QName("http://www.onvif.org/ver10/device/wsdl", "YourPortName"), YourOnvifPort.class, BindingProvider.SOAP11HTTP_BINDING ); // 或者对已创建的Port设置绑定属性 ((BindingProvider) port).getRequestContext() .put(BindingProvider.SOAP_BINDING_PROPERTY, BindingProvider.SOAP11HTTP_BINDING);
2. 是否是Jetty嵌入式服务器的SOAP 1.2支持问题?
不是。Jetty作为Servlet容器,仅负责HTTP请求的转发与处理,不直接参与SOAP协议的解析或版本控制。SOAP版本支持由JAX-WS/Jakarta WS的实现(如Eclipse Metro、Apache CXF)决定。
服务端仅支持SOAP 1.1的原因,大概率是生成服务端代码时默认采用了WSDL中的SOAP 1.1绑定,或未配置启用SOAP 1.2。若要让服务端支持SOAP 1.2,可在发布Endpoint时显式指定绑定类型:
// 发布服务时指定SOAP 1.2绑定 Endpoint.publish( "http://localhost:8080/onvif-service", new YourOnvifServiceImpl(), BindingProvider.SOAP12HTTP_BINDING );
3. 是否是Jakarta参考实现的问题?
不是。Jakarta WS的参考实现(Eclipse Metro)原生支持SOAP 1.1与SOAP 1.2。出现不对称问题的核心原因是:ONVIF WSDL通常同时定义了SOAP 1.1和SOAP 1.2的绑定,但代码生成工具默认选择的绑定版本不一致(客户端选SOAP 1.2,服务端选SOAP 1.1)。
可通过以下方式验证并修复:
- 检查服务端生成代码中的
@WebService或@BindingType注解,若未指定绑定类型,工具可能默认采用WSDL中的第一个绑定; - 在服务端实现类上添加
@BindingType(BindingProvider.SOAP12HTTP_BINDING)注解,强制启用SOAP 1.2支持; - 或采用客户端修改方案(如问题1所述),统一使用SOAP 1.1请求。
内容的提问来源于stack exchange,提问作者zebity

