百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Springboot官方例子--生成SOAP Web服务

toyiye 2024-06-21 12:32 7 浏览 0 评论

本指南将引导您完成使用Spring创建基于SOAP的Web服务的过程,这个服务将公开公开来自不同欧洲国家的数据,供你查询。

为了简化示例,您将通过硬编码编写英国、西班牙和波兰的数据。

我利用业余时间,翻译了Spring官网的例子,方便中文不好的同学,将陆续发到头条上,欢迎大家关注,也可以上我个人BLOG:itmanclub.com,上面有已经翻译过的。

程序结构

└── 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-producting-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>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 </dependencies>
 <properties>
 <java.version>1.8</java.version>
 </properties>
 <build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
 </build>
</project>

Spring Boot将会你做如下的事:

  • 将classpath里面所有用到的jar包构建成一个可执行的 JAR 文件,方便执行你的程序
  • 搜索public static void main()方法并且将它当作可执行类
  • 根据springboot版本,去查找相应的依赖类版本,当然你可以定义其它版本。

增加Spring-WS依赖

您创建的项目需要将spring-ws-core作为依赖项包含在构建文件和wsdl4j中。

对于maven:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
 <groupId>wsdl4j</groupId>
 <artifactId>wsdl4j</artifactId>
</dependency>

对于gradle:

sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
 compile("org.springframework.boot:spring-boot-starter-web-services")
 testCompile("org.springframework.boot:spring-boot-starter-test")
 compile("wsdl4j:wsdl4j:1.6.1")
 jaxb("org.glassfish.jaxb:jaxb-xjc:2.2.11")
 compile(files(genJaxb.classesDir).builtBy(genJaxb))
}

创建XML schema以定义域

Web服务域是在XML schema文件(XSD)中定义的,Spring-WS将自动导出为WSDL。

创建一个带有操作的XSD文件,以返回一个国家的名称、人口、首都和货币:

src/main/resources/countries.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring.io/guides/gs-producing-web-service"
 targetNamespace="http://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>1.6</version>
 <executions>
 <execution>
 <id>xjc</id>
 <goals>
 <goal>xjc</goal>
 </goals>
 </execution>
 </executions>
 <configuration>
 <schemaDirectory>${project.basedir}/src/main/resources/</schemaDirectory>
 <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
 <clearOutputDir>false</clearOutputDir>
 </configuration>
</plugin>

生成的类放在target/generated-sources/jaxb/目录中。

Gradle的插件配置

要对Gradle执行相同的操作,首先需要在构建文件中配置JAXB:

configurations {
 jaxb
}
bootJar {
 baseName = 'gs-producing-web-service'
 version = '0.1.0'
 from genJaxb.classesDir
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
 compile("org.springframework.boot:spring-boot-starter-web-services")
 testCompile("org.springframework.boot:spring-boot-starter-test")
 compile("wsdl4j:wsdl4j:1.6.1")
 jaxb("org.glassfish.jaxb:jaxb-xjc:2.2.11")
 compile(files(genJaxb.classesDir).builtBy(genJaxb))
}

上面的构建文件有标记和结束注释,这是为了方便你了解。您自己的构建文件中不需要这些注释。

下一步是添加由gradle使用的任务genJaxb生成Java类:

task genJaxb {
 ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
 ext.classesDir = "${buildDir}/classes/jaxb"
 ext.schema = "src/main/resources/countries.xsd"
 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) {
 arg(value: "-wsdl")
 produces(dir: sourcesDir, includes: "**/*.java")
 }
 javac(destdir: classesDir, source: 1.6, target: 1.6, 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服务提供数据,请创建一个国家/地区存储库。在本指南中,您将使用硬编码数据创建一个虚拟的国家/地区存储库实现。

package hello;
import javax.annotation.PostConstruct;
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<>();
 @PostConstruct
 public void initData() {
 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);
 }
}

创建国家/地区服务点

要创建一个服务端点,您只需要一个带有一些Spring WS 注释的POJO来处理传入的SOAP请求。

package hello;
import org.springframework.beans.factory.annotation.Autowired;
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;
import io.spring.guides.gs_producing_web_service.GetCountryRequest;
import io.spring.guides.gs_producing_web_service.GetCountryResponse;
@Endpoint
public class CountryEndpoint {
 private static final String NAMESPACE_URI = "http://spring.io/guides/gs-producing-web-service";
 private CountryRepository countryRepository;
 @Autowired
 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使用@PayloadRoot 根据消息的命名空间和本地部分选择处理程序方法。

@RequestPayload指示传入消息将映射到方法的请求参数。

@ResponsePayload注释使SpringWS将返回的值映射到响应负载。

在所有这些代码块中,io.spring.guides类将在您的IDE中显示编译时错误,除非您已经运行了基于WSDL生成域类的任务。

配置一个Web服务bean

使用Spring WS Related Beans配置创建一个新类:

package hello;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
 @Bean
 public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
 MessageDispatcherServlet servlet = new MessageDispatcherServlet();
 servlet.setApplicationContext(applicationContext);
 servlet.setTransformWsdlLocations(true);
 return new ServletRegistrationBean(servlet, "/ws/*");
 }
 @Bean(name = "countries")
 public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
 DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
 wsdl11Definition.setPortTypeName("CountriesPort");
 wsdl11Definition.setLocationUri("/ws");
 wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
 wsdl11Definition.setSchema(countriesSchema);
 return wsdl11Definition;
 }
 @Bean
 public XsdSchema countriesSchema() {
 return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
 }
}

Spring WS使用不同的servlet类型来处理SOAP消息:MessageDispatcherServlet。必须将MessageDispatcherServlet注入并设置到MessageDispatcherServlet。否则,Spring WS将无法自动检测到Spring Beans。

通过命名这个 messageDispatcherServlet bean,它不会替换Spring boot的默认DispatcherServlet bean。

DispatcherServlet配置注释驱动的SpringWS编程模型。这使得使用前面提到的@Endpoint 等各种注释成为可能。

DefaultWsdl11Definition 定义使用XsdSchema公开标准wsdl1.1

需要注意的是,您需要为MessageDispatcherServlet和DefaultWsdl11Definition指定bean名称。bean名称确定Web服务和生成的WSDL文件可用的URL。在这种情况下,WSDL将在http://<host>:<port>/ws/countries.wsdl下可用。

此配置还使用WSDL位置servlet转换servlet.setTransformWsdlLocations(true)。如果您访问http://localhost:8080/ws/countries.wsdl,soap:address将具有正确的地址。如果您改为从分配给您的机器的面向公共的IP地址访问WSDL,您将看到该地址。

创建Application

src/main/java/hello/Application.java

package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
 public static void main(String[] args) {
 SpringApplication.run(Application.class, args);
 }
}

运行和测试程序

运行Application.java,然后创建SOAP请求文件request.xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:gs="http://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接口时有几个选项。如果您使用的是*nix/mac系统,那么您可以使用SoapUI 之类的工具,或者只使用命令行工具,如下所示:

$ curl --header "content-type: text/xml" -d @request.xml http://localhost:8080/ws

因此,您应该看到此响应:

<?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="http://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>

很可能输出是一个紧凑的XML文档,而不是上面显示的格式良好的文档。如果您的系统上安装了xmllib2,那么您可以将curl -s <args above> | xmllint --format看格式较好的结果。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码