能否基于WSDL使用Java生成可用于本地测试的SOAP Server?
基于WSDL快速搭建本地SOAP测试服务的实操方案
之前做跨厂商SOAP对接时多次遇到同类场景:手里只有对方提供的WSDL,连不上正式环境,需要本地搭高度仿真的模拟服务验证客户端逻辑。Spring WS本身的设计导向是从XSD正向生成服务、自动暴露WSDL,确实不支持直接拿WSDL反向生成服务端骨架,硬套很容易出现404问题,目前最稳的方案是用Apache CXF做代码生成,整套流程跑通不需要额外适配。
具体实现步骤
- 第一步:在Maven中引入CXF代码生成插件,配置时一定要加
-server参数,不然插件默认只会生成客户端代码,不会输出服务端骨架。参考插件配置:
<plugin> <groupId>org.apache.cxf</groupId> <artifactId>cxf-codegen-plugin</artifactId> <version>3.5.5</version> <executions> <execution> <id>generate-server</id> <phase>generate-sources</phase> <configuration> <wsdlOptions> <wsdlOption> <wsdl>src/main/resources/wsdl/customer-service.wsdl</wsdl> <extraargs> <extraarg>-server</extraarg> <extraarg>-autoNameResolution</extraarg> <extraarg>-p</extraarg> <extraarg>com.xxx.soap.server</extraarg> </extraargs> </wsdlOption> </wsdlOptions> </configuration> <goals> <goal>wsdl2java</goal> </goals> </execution> </executions> </plugin>
执行mvn generate-sources之后,会在target/generated-sources目录下生成带@WebService注解的服务接口、对应的*Impl实现类,以及所有关联的JAXB实体类。
- 第二步:填充测试逻辑,打开生成的
*Impl类,里面每个接口方法默认都是返回null,直接按照测试场景构造返回对象赋值即可,不要修改类上、方法上、字段上任何JAX-WS/JAXB注解的参数,改一个就可能出现报文不匹配的问题。 - 第三步:启动服务,两种方式可选:
- 零依赖快速启动:直接用JDK自带的JAX-WS实现,写个main方法就能跑,不用搭Spring环境,纯验证客户端逻辑足够用:
public class MockServer { public static void main(String[] args) { // 地址路径必须和WSDL里soap:address定义完全一致 String publishAddr = "http://localhost:8080/soap/CustomerService"; Endpoint.publish(publishAddr, new CustomerServiceImpl()); } }- Spring/Spring Boot环境启动:引入
cxf-spring-boot-starter-jaxws依赖,注册端点Bean即可:
@Configuration public class CxfConfig { @Autowired private Bus bus; @Bean public Endpoint customerServiceEndpoint() { EndpointImpl endpoint = new EndpointImpl(bus, new CustomerServiceImpl()); endpoint.publish("/soap/CustomerService"); // 路径必须和WSDL内定义完全对齐 return endpoint; } }
高频踩坑点(基本覆盖404类问题)
- 路径不要自己随便定义:很多人启动服务后能通过默认路径访问到自动生成的WSDL就以为配置正确,实际上客户端是按照原始WSDL中
<soap:address location="xxx">里的路径发请求的,你本地发布的路径必须和这个location的路径完全一致,差一个斜杠、多一个前缀都会直接返回404。 - SOAP版本不要默认硬套:如果客户的WSDL绑定的是SOAP 1.2协议,必须在端点上显式配置SOAP 1.2的消息工厂,CXF默认用SOAP 1.1,收到1.2版本的请求会直接返回404/405,根本进不到业务逻辑。
- 不要手动修改生成代码上的注解:
@WebService上的targetNamespace、serviceName、portName,以及JAXB实体上的namespace、element name这些值,必须和WSDL定义完全一致,哪怕差一个字符,要么请求匹配不到端点返回404,要么报文序列化/反序列化失败。 - 注意WSDL里的WS策略:如果WSDL里带了WS-Security、WS-Addressing这类WS-*策略断言,要么在端点上加上对应的拦截器做适配,要么显式关闭CXF的策略校验,不然报文会被安全拦截器直接拦下,返回400/404,不会进入你写的测试逻辑。
- 代码生成遇到重名报错不要手动改类:如果wsdl2java执行时报元素重名、类重名的错误,不要手动去改生成后的类文件,在插件的extraargs里加上
<extraarg>-xjc-XautoNameResolution</extraarg>让插件自动处理命名冲突,手动改类很容易把字段的序列化注解改坏,最后返回的报文和WSDL定义对不上。
最后给个排查效率技巧:服务启动后先不要用自己写的Client去测,先用SoapUI导入原始的客户WSDL,把请求地址改成你本地的服务地址发请求,SoapUI调通了再切回自己的Client,能快速定位到底是服务端配置问题还是客户端代码问题。
内容的提问来源于stack exchange,提问作者Matt Robinson
相关产品推荐
相关产品推荐

