# 消费SOAP Web服务
本指南将引导您完成使用Spring使用基于SOAP的Web服务的过程。
## 你会建立什么
您将构建一个客户端,该客户端使用 从基于WSDL的远程Web服务中获取国家/地区数据数据 [SOAP](https://en.wikipedia.org/wiki/SOAP) 。 您可以按照 查找有关国家/地区服务的更多信息并自己运行该服务 [本指南](https://spring.io/guides/gs/producing-web-service/) 。
该服务提供国家/地区数据。 您将能够根据国家名称查询有关国家的数据。
## 你需要什么
* 约15分钟
* 最喜欢的文本编辑器或IDE
* [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 或更高版本
* [Gradle 4+](http://www.gradle.org/downloads) 或 [Maven 3.2+](https://maven.apache.org/download.cgi)
* 您还可以将代码直接导入到IDE中:
* [弹簧工具套件(STS)](https://spring.io/guides/gs/sts)
* [IntelliJ IDEA](https://spring.io/guides/gs/intellij-idea/)
## 如何完成本指南
像大多数Spring 一样 [入门指南](https://spring.io/guides) ,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。 无论哪种方式,您最终都可以使用代码。
要 **从头开始** ,请继续进行“ [从Spring Initializr开始”](https://spring.io/guides/gs/consuming-web-service/#scratch) 。
要 **跳过基础知识** ,请执行以下操作:
* [下载](https://github.com/spring-guides/gs-consuming-web-service/archive/master.zip) 并解压缩本指南的源存储库,或使用 对其进行克隆 [Git](https://spring.io/understanding/Git) : `git clone [https://github.com/spring-guides/gs-consuming-web-service.git](https://github.com/spring-guides/gs-consuming-web-service.git)`
* 光盘进入 `gs-consuming-web-service/initial`
* 前进以 [基于WSDL生成域对象](https://spring.io/guides/gs/consuming-web-service/#initial) 。
**完成后** ,您可以根据中的代码检查结果 `gs-consuming-web-service/complete`.
如果阅读了《 生产SOAP Web服务》 ,您可能会想知道为什么本指南不使用 spring-boot-starter-ws? 该Spring Boot启动器仅适用于服务器端Web服务。 该入门程序可以带入嵌入式Tomcat等功能,而无需进行Web调用。
## 在本地运行目标Web服务
请遵循 的步骤, [随附指南中](https://spring.io/guides/gs/producing-web-service/) 或克隆 [存储库](https://github.com/spring-guides/gs-producing-web-service) 并运行服务(例如,通过使用 `mvn spring-boot:run`)从 `complete`目录。 您可以通过访问来验证它是否有效 `[http://localhost:8080/ws/countries.wsdl](http://localhost:8080/ws/countries.wsdl)`在您的浏览器中。 如果您不这样做,您稍后会在JAXB工具中看到一个令人困惑的异常。
## 从Spring Initializr开始
对于所有Spring应用程序,您应该从 开始 [Spring Initializr](https://start.spring.io) 。 Initializr提供了一种快速的方法来提取应用程序所需的所有依赖项,并为您完成了许多设置。 该示例仅需要Spring Web Services依赖项。
以下清单显示了 `pom.xml` 选择Maven时创建的文件:
~~~
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>consuming-web-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consuming-web-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
~~~
以下清单显示了 `build.gradle` 选择Gradle时创建的文件:
~~~
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
~~~
## 修改构建文件
Spring Initializr创建的构建文件需要大量的工作才能完成本指南。 另外,对 `pom.xml` (对于Maven)和 `build.gradle` (对于Gradle)有很大的不同。
### Maven
For Maven, you need to add a dependency, a profile, and a WSDL generation plugin.
以下清单显示了您需要在Maven中添加的依赖项:
~~~
<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>
~~~
以下清单显示了要使其与Java 11一起使用时需要在Maven中添加的配置文件:
~~~
<profiles>
<profile>
<id>java11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
~~~
“ [基于WSDL生成域对象”](https://spring.io/guides/gs/consuming-web-service/#initial) 部分介绍了WSDL生成插件。
以下清单显示了最终的 `pom.xml` 文件:
~~~
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<!-- lookup parent from repository -->
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>consuming-web-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consuming-web-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- tag::dependency[] -->
<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>
<!-- end::dependency[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!-- tag::profile[] -->
<profiles>
<profile>
<id>java11</id>
<activation>
<jdk>[11,)</jdk>
</activation>
<dependencies>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
<!-- end::profile[] -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- tag::wsdl[] -->
<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>
<generatePackage>com.example.consumingwebservice.wsdl</generatePackage>
<schemas>
<schema>
<url>http://localhost:8080/ws/countries.wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
<!-- end::wsdl[] -->
</plugins>
</build>
</project>
~~~
### Gradle
For Gradle, you need to add a dependency, a configuration, a `bootJar` section, and a WSDL generation plugin.
The following listing shows the dependency you need to add in Gradle:
~~~
implementation ('org.springframework.boot:spring-boot-starter-web-services') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.ws:spring-ws-core'
// For Java 11:
implementation 'org.glassfish.jaxb:jaxb-runtime'
compile(files(genJaxb.classesDir).builtBy(genJaxb))
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
~~~
注意排除了Tomcat。 如果允许Tomcat在此版本中运行,则将与提供国家/地区数据的Tomcat实例发生端口冲突。
以下清单显示了 `bootJar` 您需要在Gradle中添加的部分:
~~~
bootJar {
baseName = 'gs-consuming-web-service'
version = '0.0.1'
}
~~~
“ [基于WSDL生成域对象”](https://spring.io/guides/gs/consuming-web-service/#initial) 部分介绍了WSDL生成插件。
以下清单显示了最终的 `build.gradle` 文件:
~~~
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
// tag::configurations[]
configurations {
jaxb
}
// end::configurations[]
repositories {
mavenCentral()
}
// tag::wsdl[]
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "http://localhost:8080/ws/countries.wsdl"
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
classpath: configurations.jaxb.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
xjc(destdir: sourcesDir, schema: schema,
package: "com.example.consumingwebservice.wsdl") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
debugLevel: "lines,vars,source",
classpath: configurations.jaxb.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
// end::wsdl[]
dependencies {
// tag::dependency[]
implementation ('org.springframework.boot:spring-boot-starter-web-services') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
implementation 'org.springframework.ws:spring-ws-core'
// For Java 11:
implementation 'org.glassfish.jaxb:jaxb-runtime'
compile(files(genJaxb.classesDir).builtBy(genJaxb))
jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
// end::dependency[]
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
// tag::bootjar[]
bootJar {
baseName = 'gs-consuming-web-service'
version = '0.0.1'
}
// end::bootjar[]
~~~
## Generate Domain Objects Based on a WSDL
The interface to a SOAP web service is captured in [WSDL](https://en.wikipedia.org/wiki/Web_Services_Description_Language). JAXB provides a way to generate Java classes from WSDL (or rather, the XSD contained in the `<Types/>` section of the WSDL). You can find the WSDL for the country service at `[http://localhost:8080/ws/countries.wsdl](http://localhost:8080/ws/countries.wsdl)`.
要从Maven中的WSDL生成Java类,您需要以下插件设置:
~~~
<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>
<generatePackage>com.example.consumingwebservice.wsdl</generatePackage>
<schemas>
<schema>
<url>http://localhost:8080/ws/countries.wsdl</url>
</schema>
</schemas>
</configuration>
</plugin>
~~~
此设置将为在指定URL处找到的WSDL生成类,并将这些类放入 `com.example.consumingwebservice.wsdl`包裹。 要生成该代码,请运行 `./mvnw compile` 然后看 `target/generated-sources` 如果您想检查它是否有效。
要对Gradle进行同样的操作,您将在构建文件中需要以下内容:
~~~
task genJaxb {
ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
ext.classesDir = "${buildDir}/classes/jaxb"
ext.schema = "http://localhost:8080/ws/countries.wsdl"
outputs.dir classesDir
doLast() {
project.ant {
taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
classpath: configurations.jaxb.asPath
mkdir(dir: sourcesDir)
mkdir(dir: classesDir)
xjc(destdir: sourcesDir, schema: schema,
package: "com.example.consumingwebservice.wsdl") {
arg(value: "-wsdl")
produces(dir: sourcesDir, includes: "**/*.java")
}
javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
debugLevel: "lines,vars,source",
classpath: configurations.jaxb.asPath) {
src(path: sourcesDir)
include(name: "**/*.java")
include(name: "*.java")
}
copy(todir: classesDir) {
fileset(dir: sourcesDir, erroronmissingdir: false) {
exclude(name: "**/*.java")
}
}
}
}
}
~~~
As Gradle does not (yet) have a JAXB plugin, it involves an Ant task, which makes it a bit more complex than in Maven. To generate that code run `./gradlew compileJava` and then look in `build/generated-sources` if you want to check that it worked.
在这两种情况下,JAXB域对象生成过程都已连接到构建工具的生命周期中,因此一旦构建成功,就无需运行任何额外的步骤。
## 创建国家服务客户
要创建Web服务客户端,您必须扩展 [`WebServiceGatewaySupport`](https://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/support/WebServiceGatewaySupport.html) 对您的操作进行分类和编码,如下例所示(摘自 `src/main/java/com/example/consumingwebservice/CountryClient.java`)显示:
~~~
package com.example.consumingwebservice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.client.core.SoapActionCallback;
import com.example.consumingwebservice.wsdl.GetCountryRequest;
import com.example.consumingwebservice.wsdl.GetCountryResponse;
public class CountryClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(CountryClient.class);
public GetCountryResponse getCountry(String country) {
GetCountryRequest request = new GetCountryRequest();
request.setName(country);
log.info("Requesting location for " + country);
GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate()
.marshalSendAndReceive("http://localhost:8080/ws/countries", request,
new SoapActionCallback(
"http://spring.io/guides/gs-producing-web-service/GetCountryRequest"));
return response;
}
}
~~~
The client contains one method (`getCountry`) that does the actual SOAP exchange.
在这种方法中, `GetCountryRequest` 和 `GetCountryResponse`类是从WSDL派生的,并且是在JAXB生成过程中 (在 [生成的 基于WSDL的生成域对象中进行了介绍](https://spring.io/guides/gs/consuming-web-service/#initial) )。 它创建了 `GetCountryRequest` 请求对象并使用 `country`参数(国家名称)。 在打印出国家名称后,它使用 [`WebServiceTemplate`](https://docs.spring.io/spring-ws/sites/2.0/apidocs/org/springframework/ws/client/core/WebServiceTemplate.html) 由...提供 `WebServiceGatewaySupport`基类做实际的SOAP交换。 它通过了 `GetCountryRequest` 请求对象(以及 `SoapActionCallback`传递 的 [SOAPAction](https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383528) 带有请求 标头),如WSDL描述的那样, `<soap:operation/>`元素。 它将响应转换为 `GetCountryResponse` 对象,然后将其返回。
## 配置Web服务组件
Spring WS使用Spring Framework的OXM模块,该模块具有 `Jaxb2Marshaller` 序列化和反序列化XML请求,如以下示例(来自 `src/main/java/com/example/consumingwebservice/CountryConfiguration.java`)显示:
~~~
package com.example.consumingwebservice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Configuration
public class CountryConfiguration {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
// this package must match the package in the <generatePackage> specified in
// pom.xml
marshaller.setContextPath("com.example.consumingwebservice.wsdl");
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;
}
}
~~~
The `marshaller` is pointed at the collection of generated domain objects and will use them to both serialize and deserialize between XML and POJOs.
The `countryClient` is created and configured with the URI of the country service shown earlier. It is also configured to use the JAXB marshaller.
## Run the Application
This application is packaged up to run from the console and retrieve the data for a given country name, as the following listing (from `src/main/java/com/example/consumingwebservice/ConsumingWebServiceApplication.java`) shows:
~~~
package com.example.consumingwebservice;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.example.consumingwebservice.wsdl.GetCountryResponse;
@SpringBootApplication
public class ConsumingWebServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumingWebServiceApplication.class, args);
}
@Bean
CommandLineRunner lookup(CountryClient quoteClient) {
return args -> {
String country = "Spain";
if (args.length > 0) {
country = args[0];
}
GetCountryResponse response = quoteClient.getCountry(country);
System.err.println(response.getCountry().getCurrency());
};
}
}
~~~
这 `main()` 该方法符合 [`SpringApplication`](https://docs.spring.io/spring-boot/docs/2.3.2.RELEASE/api/org/springframework/boot/SpringApplication.html) 帮手类,提供 `CountryConfiguration.class` 作为其论点 `run()`方法。 这告诉Spring从中读取注释元数据 `CountryConfiguration` 并将其作为Spring应用程序上下文中的组件进行管理。
此应用程序经过硬编码以查找“西班牙”。 在本指南的后面,您将看到如何在不编辑代码的情况下输入其他符号。
### 建立可执行的JAR
您可以使用Gradle或Maven从命令行运行该应用程序。 您还可以构建一个包含所有必需的依赖项,类和资源的可执行JAR文件,然后运行该文件。 生成可执行jar使得在整个开发生命周期中,跨不同环境等等的情况下,都可以轻松地将服务作为应用程序进行发布,版本控制和部署。
如果您使用Gradle,则可以通过使用以下命令运行该应用程序 `./gradlew bootRun`。 或者,您可以通过使用以下命令构建JAR文件: `./gradlew build` 然后运行JAR文件,如下所示:
~~~
java -jar build/libs/gs-consuming-web-service-0.1.0.jar
~~~
如果您使用Maven,则可以通过使用以下命令运行该应用程序 `./mvnw spring-boot:run`。 或者,您可以使用以下命令构建JAR文件: `./mvnw clean package` 然后运行JAR文件,如下所示:
~~~
java -jar target/gs-consuming-web-service-0.1.0.jar
~~~
The steps described here create a runnable JAR. You can also build a classic WAR file.
Logging output is displayed. The service should be up and running within a few seconds.
The following listing shows the initial response:
~~~
Requesting country data for Spain
<getCountryRequest><name>Spain</name>...</getCountryRequest>
~~~
您可以通过运行以下命令来插入其他国家/地区:
~~~
java -jar build/libs/gs-consuming-web-service-0.1.0.jar Poland
~~~
然后,响应更改为以下内容:
~~~
Requesting location for Poland
<getCountryRequest><name>Poland</name>...</getCountryRequest>
~~~
## 概括
恭喜你! 您刚刚开发了一个客户端,可以使用Spring使用基于SOAP的Web服务。
- springboot概述
- springboot构建restful服务
- spring构建一个RESTful Web服务
- spring定时任务
- 消费RESTful Web服务
- gradle构建项目
- maven构建项目
- springboot使用jdbc
- springboot应用上传文件
- 使用LDNA验证用户
- 使用 spring data redis
- 使用 spring RabbitTemplate消息队列
- 用no4j访问nosql数据库
- springboot验证web表单
- Spring Boot Actuator构j建服务
- 使用jms传递消息
- springboot创建批处理服务
- spring security保护web 安全
- 在Pivotal GemFire中访问数据
- 使用Spring Integration
- 使用springboot jpa进行数据库操作
- 数据库事务操作
- 操作mongodb
- springmvc+tymleaf创建web应用
- 将Spring Boot JAR应用程序转换为WAR
- 创建异步服务
- spring提交表单
- 使用WebSocket构建交互式Web应用程序
- 使用REST访问Neo4j数据
- jquery消费restful
- springboot跨域请求
- 消费SOAP Web服务
- springboot使用缓存
- 使用Vaadin创建CRUD UI
- 使用REST访问JPA数据
- 使用REST访问Pivotal GemFire中的数据
- 构建soap服务
- 使用rest访问mongodb数据
- 构建springboot应用docker镜像
- 从STS部署到Cloud Foundry
- springboot测试web应用
- springboot访问mysql
- springboot编写自定义模块并使用
- 使用Google Cloud Pub / Sub进行消息传递
- 构建反应式RESTful Web服务
- 使用Redis主动访问数据
- Spring Boot 部署到Kubernetes
- 使用反应式协议R2DBC访问数据
- Spring Security架构
- spring构建Docker镜像详解
- Spring Boot和OAuth2
- springboot应用部署到k8s
- spring构建rest服务详解