1. 概述
之前,我們學習瞭如何使用 Spring 創建 SOAP Web 服務。
在本教程中,我們將學習如何創建一個基於 Spring 的客户端來消費該 Web 服務。
我們之前也使用 JAX-WS RI 在 Java 中調用 SOAP Web 服務。
2. Spring SOAP Web 服務 – 快速回顧
之前,我們使用 Spring 創建了一個 Web 服務,用於根據國家名稱獲取國家數據。在深入研究客户端實現之前,我們先快速回顧一下我們是如何做到的。
遵循約定優先(contract-first)方法,我們編寫了一個 XML 模式文件,定義了領域(domain)。我們使用這個 XSD 通過 jaxb2-maven-plugin 生成了請求、響應和數據模型的類。
之後,我們編寫了四個類:
- CountryEndpoint – 響應請求的端點
- CountryRepository – 後端提供的國家數據倉庫
- WebServiceConfig – 定義所需 Bean 的配置
- Application – Spring Boot 應用,使我們的服務可供消費
最後,我們通過 cURL 測試,通過發送 SOAP 請求。
現在,讓我們通過運行上述 Boot 應用來啓動服務器,然後繼續下一步。
3. 客户端
我們將構建一個 Spring 客户端來調用並測試上述的 Web 服務。
現在,讓我們一步一步地看看如何創建客户端。
3.1. 生成客户端代碼
首先,我們將使用 WSDL(位於 http://localhost:8080/ws/countries.wsdl)生成幾個類。我們將下載並保存它到我們的 src/main/resources 文件夾中。
要使用 Maven 生成代碼,我們將向我們的 pom.xml 添加 maven-jaxb2-plugin:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.15.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<generatePackage>com.baeldung.springsoap.client.gen</generatePackage>
<schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
<schemaIncludes>
<include>countries.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>特別地,在插件配置中,我們定義了:
- generateDirectory – 生成的 Artifact 將保存到的文件夾
- generatePackage – Artifact 將使用的包名
- schemaDirectory 和 schemaIncludes – WSDL 的目錄和文件名
為了執行 JAXB 生成過程,我們將通過簡單地構建項目來執行該插件:
mvn compile有趣的是,這裏生成的工件與服務生成的工件完全相同。
我們列出將使用的工件如下:
- Country.java 和 Currency.java – POJO,表示數據模型
- GetCountryRequest.java – 請求類型
- GetCountryResponse.java – 響應類型
該服務可能部署在世界任何地方,僅通過其 WSDL,我們就可以在客户端生成與服務器相同的類!
3.2. CountryClient
接下來,我們需要擴展 Spring 的 WebServiceGatewaySupport,以便與 Web 服務進行交互。
我們將這個類命名為 CountryClient:
public class CountryClient extends WebServiceGatewaySupport {
public GetCountryResponse getCountry(String country) {
GetCountryRequest request = new GetCountryRequest();
request.setName(country);
GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate()
.marshalSendAndReceive(request);
return response;
}
}在這裏,我們定義了一個名為 getCountry 的單方法,對應於該 Web 服務所暴露的操作。在方法中,我們創建了一個 GetCountryRequest 實例並調用 Web 服務以獲取 GetCountryResponse。換句話説,這裏就是我們執行 SOAP 交換的地方。
正如我們所見,Spring 使用其 WebServiceTemplate 使調用變得非常簡單。我們使用模板的方法 marshalSendAndReceive 執行 SOAP 交換。
XML 轉換在這裏通過一個嵌入的 Marshaller 處理。
現在讓我們來看一下 Marshaller 來自哪個配置。
3.3. <em >CountryClientConfig</em >>
我們需要配置我們的 Spring WS 客户端只需要兩個 Bean。
首先,一個 <em >Jaxb2Marshaller</em >> 用於將消息轉換為 XML 和反向轉換,其次是我們的 <em >CountryClient</em >>,它會將 <em >marshaller</em >> Bean 注入其中:
@Configuration
public class CountryClientConfig {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.baeldung.springsoap.client.gen");
return marshaller;
}
@Bean
public CountryClient countryClient(Jaxb2Marshaller marshaller) {
CountryClient client = new CountryClient();
client.setDefaultUri("http://localhost:8080/ws");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
在此,我們需要確保 marshaller’s 的上下文路徑與插件配置中指定的 generatePackage 保持一致,並且位於我們的 pom.xml 中。
請注意客户端的默認 URI。它設置為 WSDL 中指定的 soap:address 位置。
4. 客户端測試
接下來,我們將編寫一個 JUnit 測試,以驗證我們的客户端是否按預期運行:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CountryClientConfig.class, loader = AnnotationConfigContextLoader.class)
public class ClientLiveTest {
@Autowired
CountryClient client;
@Test
public void givenCountryService_whenCountryPoland_thenCapitalIsWarsaw() {
GetCountryResponse response = client.getCountry("Poland");
assertEquals("Warsaw", response.getCountry().getCapital());
}
@Test
public void givenCountryService_whenCountrySpain_thenCurrencyEUR() {
GetCountryResponse response = client.getCountry("Spain");
assertEquals(Currency.EUR, response.getCountry().getCurrency());
}
}
如我們所見,我們已將 CountryClient Bean 及其配置 CountryClientConfig 集成。然後,我們使用其中的 getCountry 方法來調用前面所述的遠程服務。
此外,我們還可以使用生成的Pojo數據模型,即 Country 和 Currency,提取所需的驗證信息。
5. 結論
在本教程中,我們學習瞭如何使用 Spring WS 調用 SOAP Web 服務。
我們只是探索了 Spring 在 SOAP Web 服務領域提供的部分內容;還有很多值得探索的地方。 更多內容請參考。