本指南将引导您完成使用Spring使用基于SOAP的Web服务的过程。

你会建立什么

您将构建一个客户端,该客户端使用SOAP从基于WSDL的远程Web服务中获取国家/地区数据数据。您可以了解有关国家/地区服务的更多信息,并按照本指南自行运行服务。

该服务提供国家/地区数据。您将能够根据国家名称查询有关国家的数据。

你需要什么

如何完成本指南

像大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都可以使用工作代码。

从头开始 ,请继续使用Gradle构建

跳过基础知识 ,请执行以下操作:

完成后 ,您可以根据中的代码检查结果gs-consuming-web-service/complete

用Gradle构建

用Gradle构建

首先,您设置一个基本的构建脚本。在使用Spring构建应用程序时,可以使用任何喜欢的构建系统,但是此处包含使用GradleMaven所需的代码。如果您都不熟悉,请参阅使用Gradle 构建Java项目使用Maven构建Java项目

创建目录结构

在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello在* nix系统上:

└── src
    └── main
        └── java
            └── hello

创建一个Gradle构建文件

build.gradle

configurations {
    jaxb
}

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.1.6.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

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: "hello.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[]

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter")
    compile("org.springframework.ws:spring-ws-core")
    compile(files(genJaxb.classesDir).builtBy(genJaxb))

    jaxb "com.sun.xml.bind:jaxb-xjc:2.1.7"
}

bootJar {
    baseName = 'gs-consuming-web-service'
    version =  '0.1.0'

    from genJaxb.classesDir
}


task afterEclipseImport {
    dependsOn genJaxb
}

Spring Boot gradle插件提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。

  • 它搜索public static void main()标记为可运行类的方法。

  • 它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。

用Maven构建

用Maven构建

首先,您设置一个基本的构建脚本。使用Spring构建应用程序时,可以使用任何喜欢的构建系统,但是此处包含了使用Maven所需的代码。如果您不熟悉Maven,请参阅使用Maven 构建Java项目

创建目录结构

在您选择的项目目录中,创建以下子目录结构;例如, mkdir -p src/main/java/hello在* nix系统上:

└── src
    └── main
        └── java
            └── hello

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>

    <groupId>org.springframework</groupId>
    <artifactId>gs-consuming-web-service</artifactId>
    <version>0.1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <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.ws</groupId>
               <artifactId>spring-ws-core</artifactId>
        </dependency>
    </dependencies>

    <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.12.3</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaLanguage>WSDL</schemaLanguage>
                    <generatePackage>hello.wsdl</generatePackage>
                    <schemas>
                        <schema>
                            <url>http://localhost:8080/ws/countries.wsdl</url>
                        </schema>
                    </schemas>
                </configuration>
            </plugin>
            <!-- end::wsdl[] -->
        </plugins>
    </build>

</project>

Spring Boot Maven插件提供了许多方便的功能:

  • 它收集类路径上的所有jar,并构建一个可运行的单个“über-jar”,这使执行和传输服务更加方便。

  • 它搜索public static void main()标记为可运行类的方法。

  • 它提供了一个内置的依赖项解析器,用于设置版本号以匹配Spring Boot依赖项 。您可以覆盖所需的任何版本,但是它将默认为Boot选择的一组版本。

使用您的IDE进行构建

使用您的IDE进行构建

如果阅读了《 生产SOAP Web服务》 ,您可能想知道为什么本指南不使用spring-boot-starter-ws ?Spring Boot启动器仅用于服务器端Web服务。该入门程序可以带入嵌入式Tomcat之类的东西,而无需进行网络调用。

在本地运行目标Web服务

按照随附指南中的步骤进行操作,或仅克隆存储库并运行服务(例如,使用mvn spring-boot:run )从complete目录。您可以通过在浏览器中访问http:// localhost:8080 / ws / countries.wsdl来验证其是否正常运行。

根据WSDL生成域对象

WSDL中捕获了SOAP Web服务的接口。 JAXB提供了一种从WSDL(或更确切地说:包含在 WSDL部分)。可以在http:// localhost:8080 / ws / countries.wsdl中找到国家(地区)服务的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>hello.wsdl</generatePackage>
        <schemas>
            <schema>
                <url>http://localhost:8080/ws/countries.wsdl</url>
            </schema>
        </schemas>
    </configuration>
</plugin>

此设置将为在指定URL找到的WSDL生成类,并将这些类放入hello.wsdl包。

要使用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: "hello.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")
                }
            }
        }
    }
}

由于gradle还没有JAXB插件,因此它涉及到ant任务,这使其比maven更加复杂。

在这两种情况下,JAXB域对象生成过程都已连接到构建工具的生命周期中,因此没有多余的步骤可运行。

创建国家服务客户

要创建Web服务客户端,只需扩展WebServiceGatewaySupport类并编写操作代码即可:

src/main/java/hello/CountryClient.java

package hello;

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 hello.wsdl.GetCountryRequest;
import hello.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;
	}

}

客户端包含一种方法: getCountry进行实际的SOAP交换。

在这种方法中, GetCountryRequestGetCountryResponse类是从WSDL派生的,并且是在上一步中描述的JAXB生成过程中生成的。它创建了GetCountryRequest请求对象并使用country参数(国家名称)。打印出国家/地区名称后,它将使用由国家/地区提供的WebServiceTemplate WebServiceGatewaySupport基类做实际的SOAP交换。它通过了GetCountryRequest请求对象,以及SoapActionCallback传递带有请求的SOAPAction标头,因为WSDL描述了它需要元素。它将响应转换为GetCountryResponse对象,然后将其返回。

配置Web服务组件

Spring WS使用Spring Framework的OXM模块,该模块具有Jaxb2Marshaller序列化和反序列化XML请求。

src/main/java/hello/CountryConfiguration.java

package hello;

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("hello.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;
	}

}

marshaller指向生成的域对象的集合,并将用它们在XML和POJO之间进行序列化和反序列化。

countryClient使用上面显示的国家/地区服务的URI创建和配置。它还配置为使用JAXB编组器。

使应用程序可执行

该应用程序打包成可从控制台运行并检索给定国家/地区名称的数据:

src/main/java/hello/Application.java

package hello;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import hello.wsdl.GetCountryResponse;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.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帮手类,提供CountryConfiguration.class作为其论点run()方法。这告诉Spring从中读取注释元数据CountryConfiguration并将其作为Spring应用程序上下文中的组件进行管理。

此应用程序经过硬编码以查找与Microsoft Corporation相对应的符号'MSFT'。在本指南的结尾,您将看到如何在不编辑代码的情况下插入其他符号。

构建可执行的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
此处描述的步骤将创建可运行的JAR。您还可以构建经典的WAR文件

显示日志记录输出。该服务应在几秒钟内启动并运行。

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服务。

也可以看看

以下指南也可能会有所帮助:

是否要编写新指南或为现有指南做出贡献?查看我们的贡献准则

所有指南均以代码的ASLv2许可证和写作的Attribution,NoDerivatives创作共用许可证发布