Spring中的Web Service消费者集成(应该被淘汰的技术)
问题
最近需要对接一个老系统的web service接口,我已经有7,8年没有遇到过这种接口了。
思路
先用Spring空项目中的jaxws-maven-plugin插件生成一波web service客户端,然后,集成到现有的SpringBoot3项目中使用就可以了。
生成web service客户端代码
直接使用Consuming a SOAP web service的文章空Spring项目,然后,直接在这个项目使用已经集成好的jaxws-maven-plugin插件生产web service客户端代码即可。
注意:这里需要提前把WSDL文件准备好放在本地。
拉取一下示例代码:
git clone https://github.com/spring-guides/gs-consuming-web-service.git
进入initial
文件夹,修改pom.xml:
具体添加如下内容:
<plugin><groupId>com.sun.xml.ws</groupId><artifactId>jaxws-maven-plugin</artifactId><version>3.0.0</version><executions><execution><goals><goal>wsimport</goal></goals></execution></executions><configuration><!-- 需要的工程包名 --><packageName>com.xx.xxx.wsdl</packageName><wsdlFiles><!-- 需要解析本地WSDL文件 --><wsdlFile>${project.basedir}/src/wsdl/xxxx.wsdl</wsdlFile></wsdlFiles><sourceDestDir>${sourcesDir}</sourceDestDir><destDir>${classesDir}</destDir><extension>true</extension></configuration>
</plugin>
然后,在这个目录${project.basedir}/src/wsdl/xxxx.wsdl
保持需要对接的WSDL文件,如果开发环境能够正常访问web service的wsdl文件,则可以wsdlUrls替代wsdlFiles,类似配置如下:
<wsdlUrls><wsdlUrl>http://localhost:8080/ws/countries.wsdl</wsdlUrl>
</wsdlUrls>
最后,运行./mvnw compile
命令,则可以在target/generated-sources目录找到生成的web service客户端代码。具体在 如下:
将客户端代码集成到SpringBoot项目中
将上述生成在wsdl包项目的客户端代码复制到已有的SpringBoot源代码工程中即可。复制完成后,需要引入spring-boot-starter-web-services
依赖,需要去掉其中的tomcat依赖,以免重复依赖,具体配置如下:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web-services</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions>
</dependency>
完成上面maven依赖后,需要进一步配置spring-boot-starter-web-services
,具体就是配置 Web Service的客户端类和通用配置类:
WsClient.java
package com.xxx.xxxx.wsdl;import lombok.extern.slf4j.Slf4j;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;/*** web service客户端*/
@Slf4j
public class WsClient extends WebServiceGatewaySupport {public int sxWork(String xml, String xxx){log.info("消息:{}", uniteWorkXml);// 这里的SxxxWork类,不过是,之前根据web service服务生成的请求类SxxxWork sxxxWork = new SxxxWork();sxxxWork.setArg0(xml);sxxxWork.setArg1(xxx);// 这里是关键,使用getWebServiceTemplate()的marshalSendAndReceive方法来调用web service// 这里请求参数和返回参数,都是依赖 web service服务的接口类定义return (int) getWebServiceTemplate().marshalSendAndReceive(sxxxWork);}}
WsxxxConfiguration.java
下面是web service客户端的xml序列化与反序列化配置,具体如下:
package com.xxx.xxxx.wsdl;import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;@Configuration
@RefreshScope
public class WsxxxConfiguration {@Value("${web-service.uri}")private String uri;@Beanpublic Jaxb2Marshaller marshaller() {Jaxb2Marshaller marshaller = new Jaxb2Marshaller();// this package must match the package in the <generatePackage> specified in// pom.xml// 这里主要是告诉jaxb需要解析xml与java bean相互转化的模型类在哪里marshaller.setContextPath("com.xxx.xxxx.wsdl");return marshaller;}@Beanpublic WsClient wsClient(Jaxb2Marshaller marshaller) {WsClient client = new WsClient();client.setDefaultUri(uri);// web service客户端的xml序列化与反序列化使用Jaxbclient.setMarshaller(marshaller);client.setUnmarshaller(marshaller);return client;}
}
看吧,序列化成xml,这是json的前辈。到这里,就可以在Spring中自动注入WsClient.java类,来调用第三方web service方法。
总结
Web Service这种技术,我是看好几天,才大概摸明白这个协议,上次我真正对接这个技术的时候,还是入行初期,这东西都快被淘汰,wsdl太难看懂了。
希望之后的时光,不要遇到wsdl这种东西。
参考:
- Consuming a SOAP web service
- jaxws:wsimport
- JAXB使用
- Web服务
- Consuming a SOAP web service
- Web Service Client in Spring Boot
- Web Services Description Language
- Web Service Client in Spring Boot