前言
前面我们已经整合spring-ws
实现了web service的服务端:Spring Boot整合spring-ws开发web service
接下来就是实现客户端进行调用了。
添加依赖
客户端,同样的需要先添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
获取wsdl文件
服务端由一个xsd文件开始,客户端则是由一个wsdl文件开始。
获取wsdl文件也十分简单,用浏览器访问web service地址,然后另存为即可。当然也可以直接用url地址来生成代码,只不过我习惯本地另存为后再生成。
完整的wsdl文件内容如下:
<wsdl:definitions
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:sch="http://www.dexcoder.com/ws"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.dexcoder.com/ws" targetNamespace="http://www.dexcoder.com/ws">
<wsdl:types>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.dexcoder.com/ws">
<xs:element name="getCountryRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountryResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="country" type="tns:country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="country">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
<xs:element name="capital" type="xs:string"/>
<xs:element name="currency" type="tns:currency"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="currency">
<xs:restriction base="xs:string">
<xs:enumeration value="GBP"/>
<xs:enumeration value="EUR"/>
<xs:enumeration value="PLN"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getCountryResponse">
<wsdl:part element="tns:getCountryResponse" name="getCountryResponse"></wsdl:part>
</wsdl:message>
<wsdl:message name="getCountryRequest">
<wsdl:part element="tns:getCountryRequest" name="getCountryRequest"></wsdl:part>
</wsdl:message>
<wsdl:portType name="CountriesPort">
<wsdl:operation name="getCountry">
<wsdl:input message="tns:getCountryRequest" name="getCountryRequest"></wsdl:input>
<wsdl:output message="tns:getCountryResponse" name="getCountryResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CountriesPortSoap11" type="tns:CountriesPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getCountry">
<soap:operation soapAction=""/>
<wsdl:input name="getCountryRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getCountryResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CountriesPortService">
<wsdl:port binding="tns:CountriesPortSoap11" name="CountriesPortSoap11">
<soap:address/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
添加maven的jaxb2插件生成代码
跟服务端根据xsd来生成代码类似,客户端同样可以根据wsdl来生成代码。maven插件依赖:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.12.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>com.dexcoder.ws</generatePackage>
<generateDirectory>${basedir}/src/main/java</generateDirectory>
<schemas>
<schema>
<fileset>
<!-- Defaults to schemaDirectory. -->
<directory>${basedir}/src/main/resources/schemas</directory>
<!-- Defaults to schemaIncludes. -->
<includes>
<include>*.wsdl</include>
</includes>
<!-- Defaults to schemaIncludes -->
<!--<excludes>-->
<!--<exclude>*.xs</exclude>-->
<!--</excludes>-->
</fileset>
<!--<url>http://localhost:8080/ws/countries.wsdl</url>-->
</schema>
</schemas>
</configuration>
</plugin>
同样mvn install之后将生成客户端代码。这里生成的代码跟我们前面发布的服务端代码应该是一样的,当然包名可能不同这个由你指定。
在生成代码的同时会生成META-INF
文件夹,这个可以移到resources目录下或者直接删除都没有关系。生成后的项目结构图:
编写ws客户端
生成了代码之后,编写客户端变的很容易,具体代码如下:
public class WsClient extends WebServiceGatewaySupport {
public GetCountryResponse getCountry(String name) {
GetCountryRequest request = new GetCountryRequest();
request.setName(name);
GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate().marshalSendAndReceive(
"http://localhost:8080/ws/countries.wsdl", request);
return response;
}
}
配置ws客户端
编写完一切代码之后,同样需要配置到spring boot才行,ContextPath
指定刚才生成代码所在的包名,它会到该包下去寻找相应的类自动进行数据转换:
@Configuration
public class WSConfig {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.dexcoder.ws");
return marshaller;
}
@Bean
public WsClient wsClient(Jaxb2Marshaller marshaller) {
WsClient client = new WsClient();
client.setDefaultUri("http://localhost:8080/ws/countries.wsdl");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
运行
到这里所有的调用代码都已经完成了,剩下的就是运行来检测是否调用成功。
这里我们来编写一个Controller
来简单测试一下。
@RestController
public class IndexController {
@Autowired
private WsClient wsClient;
@RequestMapping("callws")
public Object callWs() {
GetCountryResponse response = wsClient.getCountry("hello");
return response.getCountry();
}
}
使用了RestController
,直接将调用ws返回的数据用json格式输出到页面。
启动spring boot,访问http://localhost:8081/callws 这里把端口换成了8081,因为默认的8080已经被前面的服务端占用了。
可以看到成功调用了ws的服务端并返回了数据,hello部分为我们发送过去的参数: