本指南将指导您使用Spring使用基于SOAP的Web服务。您将构建一个客户端,该客户端使用SOAP从基于WSDL的Webservice服务获取国家数据。您将能够根据某个国家的名称查询该国家的数据。
程序结构
└── 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将会你做如下的事:
- 将 classpath 里面所有用到的jar包构建成一个可执行的 JAR 文件,方便执行你的程序
- 搜索public static void main()方法并且将它当作可执行类
- 根据springboot版本,去查找相应的依赖类版本,当然你可以定义其它版本。
在本地运行目标Web服务
按照指南中的步骤操作,或者只拷贝存储库并从其完整目录运行服务(例如,使用mvn spring-boot:run)。您可以通过在浏览器中访问http://localhost:8080/ws/countries.wsdl来验证是否有效。
生成基于WSDL的域对象
SOAP Web服务的描述写在WSDL中。JAXB提供了一种从WSDL(或更确切地说,在WSDL的<Types/>
节中包含的XSD)生成Java类的简单方法。本次国家查询服务的WSDL可以在http://localhost:8080/ws/countries.wsdl上找到。
要从Maven中的WSDL生成Java类,需要在pon.xml中增加如下设置:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</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交换。
在这个方法中,GetCountryRequest和GetCountryResponse类都是从WSDL派生的,并且是在前面步骤中描述的JAXB生成过程中生成的。它创建GetCountryRequest请求对象,并使用country参数(国家名称)对其进行设置。打印出国家/地区名称后,它使用WebServiceGatewaySupport基类提供的WebServiceTemplate进行实际的SOAP交换。它传递GetCountryRequest请求对象,以及SoapActionCallback来传递带有请求的SOAPAction头,正如WSDL在<soap:operation/>
元素中描述的那样。它将响应强制转换为GetCountryResponse 对象,然后返回该对象。
配置Web服务组件
SpringWS使用Spring框架的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的marshaller。
创建应用程序Application
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帮助程序类,为其runrun() 方法提供CountryConfiguration.class作为参数。这告诉Spring从CountryConfiguration中读取注释元数据,并将其作为Spring应用程序上下文中的组件进行管理。
此应用程序硬编码以查找对应于Microsoft Corporation的号“MSFT”。在本指南的最后,您将看到如何在不编辑代码的情况下插入其他符号。
执行并测试程序
可以直接使用前面的Appcation,运行程序,日志输出是打开的,服务应该在几秒钟内启动并运行。
请求西班牙的国家数据
<getCountryRequest><name>Spain</name>...</getCountryRequest>
您可以通过键入java -jar build/libs/gs-consuming-web-service-0.1.0.jar Poland
来插入Poland国家。
请求波兰的数据:
<getCountryRequest><name>Poland</name>...</getCountryRequest>