本指南介绍如何使用Spring创建基于SOAP的Web服务服务器。
将构建什么
你将构建一个服务器,通过基于WSDL的SOAP Web服务公开欧洲国家的数据。
| 为简化示例,将英国、西班牙和波兰的数据硬编码在程序中。 |
准备条件
-
约15分钟。
-
熟悉的文本编辑器或IDE。
-
Java 17或更高版本。
-
也可以直接将代码导入IDE:
如何完成本指南
与大多数Spring入门指南一样,可以从零逐步完成,也可以跳过已熟悉的基础设置,最终得到可工作的代码。
从零开始时,请进入使用Spring Initializr一节。
要跳过基础设置,请执行:
-
下载并解压本指南的源码仓库,或使用Git克隆:
git clone https://github.com/spring-guides/gs-soap-service.git。仓库地址:https://github.com/spring-guides/gs-soap-service.git。 -
进入
gs-soap-service/initial目录。 -
跳到添加WSDL运行时依赖。
完成后,可将结果与gs-soap-service/complete中的代码比较。
使用Spring Initializr
可以打开预配置项目,点击Generate下载ZIP。该项目已经按本教程示例完成配置。
手动初始化项目:
-
进入https://start.spring.io。该服务会引入应用所需依赖,并完成大部分初始设置。
-
选择Gradle或Maven,以及使用的语言。本指南假定选择Java。
-
点击Dependencies,选择Spring Web Services。
-
点击Generate。
-
下载生成的ZIP,其中是按照所选配置创建的Web应用。
| 如果IDE集成了Spring Initializr,也可以在IDE中完成这些步骤。 |
添加WSDL运行时依赖
服务在运行时需要wsdl4j,将它添加到Gradle构建中:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webservices'
runtimeOnly 'wsdl4j:wsdl4j'
testImplementation 'org.springframework.boot:spring-boot-starter-webservices-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
或者添加到POM文件:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webservices</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webservices-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
创建定义领域的XML Schema
Web服务的领域通过XML Schema文件(XSD)定义,Spring-WS会自动将其导出为WSDL。
创建XSD,定义返回国家名称、人口、首都和货币的操作。以下内容来自src/main/resources/META-INF/schemas/countriesWs.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="https://spring.io/guides/gs-producing-web-service"
targetNamespace="https://spring.io/guides/gs-producing-web-service" elementFormDefault="qualified">
<xs:element name="getCountryRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCountryResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="country" type="tns:country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="country">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
<xs:element name="capital" type="xs:string"/>
<xs:element name="currency" type="tns:currency"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="currency">
<xs:restriction base="xs:string">
<xs:enumeration value="GBP"/>
<xs:enumeration value="EUR"/>
<xs:enumeration value="PLN"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
根据XML Schema生成领域类
下一步根据XSD生成Java类。合适的方式是在构建期间,通过Maven或Gradle插件自动生成。
Maven所需插件配置如下:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>4.0.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/META-INF/schemas/countriesWs.xsd</source>
</sources>
</configuration>
</plugin>
生成类位于target/generated-sources/jaxb/目录。
使用Gradle时,在插件区域声明新插件:
id 'com.github.bjornvester.xjc' version '1.9.1'
然后将其配置为指向XSD文件所在位置:
xjc {
xsdDir.set(layout.projectDirectory.dir("src/main/resources/META-INF/schemas"))
}
两种方式都会把JAXB领域对象生成过程接入构建工具生命周期,无需额外运行步骤。
创建国家数据仓库
为了向Web服务提供数据,需要创建国家数据仓库。本指南使用硬编码数据构建一个模拟实现。以下代码来自src/main/java/com/example/producingwebservice/CountryRepository.java:
package com.example.producingwebservice;
import java.util.HashMap;
import java.util.Map;
import io.spring.guides.gs_producing_web_service.Country;
import io.spring.guides.gs_producing_web_service.Currency;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
@Component
public class CountryRepository {
private static final Map<String, Country> countries = new HashMap<>();
static {
Country spain = new Country();
spain.setName("Spain");
spain.setCapital("Madrid");
spain.setCurrency(Currency.EUR);
spain.setPopulation(46704314);
countries.put(spain.getName(), spain);
Country poland = new Country();
poland.setName("Poland");
poland.setCapital("Warsaw");
poland.setCurrency(Currency.PLN);
poland.setPopulation(38186860);
countries.put(poland.getName(), poland);
Country uk = new Country();
uk.setName("United Kingdom");
uk.setCapital("London");
uk.setCurrency(Currency.GBP);
uk.setPopulation(63705000);
countries.put(uk.getName(), uk);
}
public Country findCountry(String name) {
Assert.notNull(name, "The country's name must not be null");
return countries.get(name);
}
}
创建国家服务端点
只需在普通Java对象(POJO)上添加少量Spring WS注解,就可以创建处理SOAP请求的服务端点。以下类来自src/main/java/com/example/producingwebservice/CountryEndpoint.java:
package com.example.producingwebservice;
import io.spring.guides.gs_producing_web_service.GetCountryRequest;
import io.spring.guides.gs_producing_web_service.GetCountryResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
@Endpoint
public class CountryEndpoint {
private static final String NAMESPACE_URI = "https://spring.io/guides/gs-producing-web-service";
private final CountryRepository countryRepository;
public CountryEndpoint(CountryRepository countryRepository) {
this.countryRepository = countryRepository;
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
@ResponsePayload
public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
GetCountryResponse response = new GetCountryResponse();
response.setCountry(countryRepository.findCountry(request.getName()));
return response;
}
}
@Endpoint将此类注册为Spring WS处理入站SOAP消息的候选者。
Spring WS根据消息的命名空间与localPart,使用@PayloadRoot选择处理方法。
@RequestPayload表示将入站消息映射到方法的请求参数。
@ResponsePayload让Spring WS把方法返回值映射为响应负载。
在这些代码中,若尚未运行生成领域类的任务,IDE会报告io.spring.guides类的编译错误。原文在这里将生成依据称为WSDL;本指南前面的生成配置实际使用XSD。 |
公开Web服务
现在公开服务,让客户端能够获取WSDL定义。Spring Boot会扫描配置位置中的所有.xsd和.wsdl文件。首先编辑src/main/resources/application.properties,声明Schema文件位置:
spring.webservices.wsdl-locations=classpath:META-INF/schemas/
Spring Boot会创建名称与文件名相同的SimpleXsdSchema或DefaultWsdl11Definition Bean。这里会得到名为countriesWs的SimpleXsdSchema Bean,可用它创建对外提供WSDL的Bean。创建src/main/java/com/example/producingwebservice/WebServiceConfig.java,内容如下:
package com.example.producingwebservice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
@Configuration(proxyBeanMethods = false)
public class WebServiceConfig {
@Bean
public DefaultWsdl11Definition countries(SimpleXsdSchema countriesWs) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("CountriesPort");
wsdl11Definition.setLocationUri("/services");
wsdl11Definition.setTargetNamespace("https://spring.io/guides/gs-producing-web-service");
wsdl11Definition.setSchema(countriesWs);
return wsdl11Definition;
}
}
DefaultWsdl11Definition使用已配置的XsdSchema提供标准WSDL 1.1定义。
DefaultWsdl11Definition的Bean名称决定生成的WSDL文件URL。本例为http://<host>:<port>/services/countries.wsdl,其中主机和端口是待替换的占位符。 |
默认通过/services HTTP端点公开服务,也可以通过spring.webservices.path属性定制。
测试应用
应用运行后即可测试。创建request.xml,包含以下SOAP请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="https://spring.io/guides/gs-producing-web-service">
<soapenv:Header/>
<soapenv:Body>
<gs:getCountryRequest>
<gs:name>Spain</gs:name>
</gs:getCountryRequest>
</soapenv:Body>
</soapenv:Envelope>
测试SOAP接口有几种方式。可以使用SoapUI之类的工具,或在类Unix、Mac系统上使用命令行工具。下面使用curl:
# Use data from file
$ curl --header "Content-Type: text/xml" -d @request.xml http://localhost:8080/services | xmllint --format
预期响应如下:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getCountryResponse xmlns:ns2="https://spring.io/guides/gs-producing-web-service">
<ns2:country>
<ns2:name>Spain</ns2:name>
<ns2:population>46704314</ns2:population>
<ns2:capital>Madrid</ns2:capital>
<ns2:currency>EUR</ns2:currency>
</ns2:country>
</ns2:getCountryResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
总结
至此,已完成使用Spring Web Services构建SOAP服务的步骤。
另请参阅
以下指南也可能有帮助:
要编写新指南或改进现有指南,可查阅贡献指南。
| 所有指南的代码采用Apache License 2.0(ASLv2),文字采用知识共享署名—禁止演绎许可。相应版权与许可声明继续适用。 |
原文:创建Spring SOAP Web服务;作者:Spring Guides贡献者。版本或日期:官方原文抓取版本。原文及源码权利归相应权利人所有。











暂无评论内容