Invoking a SOAP Web Service in Spring – 在Spring中调用一个SOAP网络服务

最后修改: 2020年 4月 29日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Previously, we saw how to create a SOAP web service with Spring.

之前,我们看到了如何用Spring创建一个SOAP web服务

In this tutorial, we’ll learn how to create a Spring-based client to consume this web service.

在本教程中,我们将学习如何创建一个基于Spring的客户端来消费这个Web服务

In invoking a SOAP web service in Java, we did the same using JAX-WS RI.

在Java中调用一个SOAP web服务中,我们使用JAX-WS RI做了同样的事情。

2. The Spring SOAP Web Service – a Quick Recap

2.Spring SOAP网络服务–快速回顾

Earlier, we had created a web service in Spring to fetch a country’s data, given its name. Before delving into the client implementation, let’s do a quick recap of how we’d done that.

早些时候,我们在Spring中创建了一个Web服务来获取一个国家的数据,并给出了它的名称。在深入研究客户端的实现之前,让我们快速回顾一下我们是如何做到这一点的。

Following the contract-first approach, we first wrote an XML schema file defining the domain. We then used this XSD to generate classes for the request, response, and data model using the jaxb2-maven-plugin.

按照契约优先的方法,我们首先编写了一个定义领域的XML模式文件。然后我们用这个XSD为请求、响应和数据模型生成类,并使用jaxb2-maven-plugin

After that we coded four classes:

之后,我们对四个类进行了编码。

Finally, we tested it via cURL by sending a SOAP request.

最后,我们通过cURL发送一个SOAP请求来测试它。

Now let’s start the server by running the above Boot app and move on to the next step.

现在让我们通过运行上述Boot应用程序来启动服务器,并进入下一个步骤。

3. The Client

3.客户

Here, we’re going to build a Spring client to invoke and test the above web service.

在这里,我们将构建一个Spring客户端来调用和测试上述Web服务

Now, let’s see step-by-step what all we need to do in order to create a client.

现在,让我们逐步看看为了创建一个客户,我们需要做什么。

3.1. Generate Client Code

3.1.生成客户端代码

First, we’ll generate a few classes using the WSDL available at http://localhost:8080/ws/countries.wsdl. We’ll download and save this in our src/main/resources folder.

首先,我们将使用在http://localhost:8080/ws/countries.wsdl上提供的WSDL生成几个类。我们将下载并保存在我们的src/main/resources文件夹中。

To generate code using Maven, we’ll add the maven-jaxb2-plugin to our pom.xml:

为了使用Maven生成代码,我们将把maven-jaxb2-plugin加入我们的pom.xml

<plugin> 
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.14.0</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>

Notably, in the plugin configuration we defined:

值得注意的是,在插件配置中,我们定义了。

  • generateDirectory – the folder where the generated artifacts will be saved
  • generatePackage – the package name that the artifacts will use
  • schemaDirectory and schemaIncludes – the directory and file name for the WSDL

To carry out the JAXB generation process, we’ll execute this plugin by simply building the project:

为了进行JAXB的生成过程,我们将通过简单地构建项目来执行这个插件。

mvn compile

Interestingly, the artifacts generated here are the same as those generated for the service.

有趣的是,这里生成的工件与为服务生成的工件相同。

Let’s list down the ones we’ll be using:

让我们列举一下我们要使用的那些东西。

  • Country.java and Currency.java – POJOs representing the data model
  • GetCountryRequest.java – the request type
  • GetCountryResponse.java – the response type

The service might be deployed anywhere in the world, and with just its WSDL, we were able to generate the same classes at the client end as the server!

该服务可能被部署在世界的任何地方,仅凭它的WSDL,我们就能在客户端生成与服务器相同的类。

3.2. CountryClient

3.2.CountryClient

Next, we need to extend Spring’s WebServiceGatewaySupport to interact with the web service.

接下来,我们需要扩展Spring的WebServiceGatewaySupport来与Web服务进行交互。

We’ll call this class CountryClient:

我们将这个类称为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;
    }
}

Here, we defined a single method getCountry, corresponding to the operation that the web service had exposed. In the method, we created a GetCountryRequest instance and invoked the web service to get a GetCountryResponse. In other words, here’s where we performed the SOAP exchange.

在这里,我们定义了一个方法getCountry,对应于网络服务所暴露的操作。在该方法中,我们创建了一个GetCountryRequest实例,并调用网络服务以获得GetCountryResponse。换句话说,这里是我们进行SOAP交换的地方

As we can see, Spring made the invocation pretty straightforward with its WebServiceTemplate. We used the template’s method marshalSendAndReceive to perform the SOAP exchange.

我们可以看到,Spring通过其WebServiceTemplate使调用变得非常简单。我们使用模板的方法marshalSendAndReceive来执行SOAP交换。

The XML conversions are handled here via a plugged-in Marshaller.

这里的XML转换是通过一个插入式的Marshaller.处理的。

Now let’s look at the configuration where this Marshaller is coming from.

现在让我们来看看这个Marshaller来自哪里的配置。

3.3. CountryClientConfig

3.3.CountryClientConfig

All we need to configure our Spring WS client are two beans.

我们需要配置我们的Spring WS客户端的是两个Bean。

First, a Jaxb2Marshaller to convert messages to and from XML, and second, our CountryClient, which will wire in the marshaller bean:

首先,一个Jaxb2Marshaller将消息转换为XML,其次是我们的CountryClient,它将连接到marshallerbean。

@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;
    }
}

Here, we need to take care that the marshaller‘s context path is the same as generatePackage specified in the plugin configuration of our pom.xml.

在这里,我们需要注意marshaller的上下文路径与我们pom.xml的插件配置中指定的generatePackage相同。

Please also notice the default URI for the client here. It’s set as the soap:address location specified in the WSDL.

请注意这里的客户端的默认URI。它被设置为WSDL中指定的soap:address位置。

4. Testing the Client

4.测试客户

Next, we’ll write a JUnit test to verify that our client is functioning as expected:

接下来,我们将写一个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());
    }
}

As we can see, we wired in the CountryClient bean defined in our CountryClientConfig. Then, we used its getCountry to invoke the remote service as described earlier.

正如我们所看到的,我们在CountryClient中定义了CountryClientConfig的bean。然后,我们使用它的getCountry来调用远程服务,如前所述。

Moreover, we were able to extract the information we needed for our assertions using the generated data model POJOs, Country, and Currency.

此外,我们能够使用生成的数据模型POJO、Country,Currency提取我们的断言所需的信息。

5. Conclusion

5.总结

In this tutorial, we saw the basics of how to invoke a SOAP web service using Spring WS.

在本教程中,我们看到了如何使用Spring WS调用SOAP Web服务的基础知识

We merely scratched the surface of what Spring has to offer in the SOAP web services area; there’s lots to explore.

我们仅仅触及了Spring在SOAP Web服务领域所提供的内容的表面;还有很多东西需要探索

As always, source code is available over on GitHub.

一如既往,源代码可在GitHub上获取。