Spring Boot SOAP Web服务示例
在本教程中,我们将看到如何使用Spring Boot创建SOAP Web服务。
我们将使用Spring Boot创建合同First SOAP Web服务。
我们将专注于如何定义SOAP Web服务的配置。
使用的工具
- JDK 1.8,Eclipse,Maven
- Spring boot - 基础应用程序框架
- WSDL4J - 用于为我们的服务发布WSDL
- JAXB Maven插件 - 用于代码生成
- SOAP-UI - 用于测试我们的SOAP Web服务
项目结构
让我们创建一个简单的Spring启动应用程序。
第1步:转到"https://start.spring.io/"并根据下面的屏幕截图创建Spring启动项目。
第2步:在Eclipse中导入Maven项目。
添加WSDL4J依赖项
步骤3:将WSDL4J依赖添加到POM。
<dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> </dependency>
XSD文件定义域
步骤4:在资源文件夹中创建名为"book.xsd"的XSD文件。
正如我们创建合同的第一个SOAP Web服务,我们需要定义Spring-WS将自动导出为WSDL的XML模式文件(XSD)。
我们正在创建Book.xsd,它将使用其ID,标题和页数返回书籍。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="https://www.theitroad.com/xml/book" targetNamespace="https://www.theitroad.com/xml/book" elementFormDefault="qualified"> <xs:element name="getBookRequest"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:int" </xs:sequence> </xs:complexType> </xs:element> <xs:element name="getBookResponse"> <xs:complexType> <xs:sequence> <xs:element name="Book" type="tns:Book" </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="Book"> <xs:sequence> <xs:element name="id" type="xs:int" <xs:element name="title" type="xs:string" <xs:element name="pages" type="xs:long" </xs:sequence> </xs:complexType> </xs:schema>
基于XSD生成域类
步骤5:我们现在将基于XSD生成域类。
我们将使用JAXB Maven插件基于XSD生成域类。
用于Maven的插件配置
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <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>
因此,当我们运行Maven Build时,将生成这些域类。
创建带有虚拟数据的书籍存储库
步骤6:创建BookRepository.java.This存储库将为Web服务提供伪数据。
package org.igi.theitroad; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import com.theitroad.xml.book.Book; @Component public class BookRepository { private static final Map<Integer, Book> books = new HashMap<>(); @PostConstruct public void initData() { Book javaBook = new Book(); javaBook.setId(1); javaBook.setTitle("Head first java"); javaBook.setPages(400); books.put(javaBook.getId(), javaBook); Book springBook = new Book(); springBook.setId(2); springBook.setTitle("Spring in action"); springBook.setPages(400); books.put(springBook.getId(), springBook); Book pythonBook = new Book(); pythonBook.setId(3); pythonBook.setTitle("Learning Python"); pythonBook.setPages(400); books.put(pythonBook.getId(), pythonBook); Book hiberanteBook = new Book(); hiberanteBook.setId(4); hiberanteBook.setTitle("Hibernate in action"); hiberanteBook.setPages(400); books.put(hiberanteBook.getId(), hiberanteBook); } public Book findBookById(int id) { Assert.notNull(id, "The book's name must not be null"); return books.get(id); } }
定义书籍服务端点
步骤7:要创建书籍服务端点,我们只需用Spring Ws注释向Pojo注释为处理SOAP请求。
package org.igi.theitroad; 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 com.theitroad.xml.book.GetBookRequest; import com.theitroad.xml.book.GetBookResponse; @Endpoint public class BookEndpoint { private static final String NAMESPACE_URI = "https://www.theitroad.com/xml/book"; private BookRepository bookRepository; @Autowired public BookEndpoint(BookRepository bookRepository) { this.bookRepository = bookRepository; } @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getBookRequest") @ResponsePayload public GetBookResponse getCountry(@RequestPayload GetBookRequest request) { GetBookResponse response = new GetBookResponse(); response.setBook(bookRepository.findBookById(request.getId())); return response; } }
让我们查看有关上述注释的更多详细信息。
@endpoint:此注释用于注册带有Spring WS的类,用于处理传入的SOAP请求。
@PayLoadRoot:此注释可帮助Spring WS根据消息的命名空间和LocalPart选择处理程序方法。
@ResponsePayload:此注释表示传入消息将映射到方法的请求参数。
@ResponsePayload:此注释用于Spring WS将返回值映射到响应有效载荷。
定义Web服务配置
第8步:创建一个名为WebServiceConfiguration.java的新类,其中包含Spring Web服务相关的Bean配置。
package org.igi.theitroad; 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 WebServiceConfiguration 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 = "booksWsdl") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema booksSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("BooksPort"); wsdl11Definition.setLocationUri("/ws"); wsdl11Definition.setTargetNamespace("https://www.theitroad.com/xml/book"); wsdl11Definition.setSchema(booksSchema); return wsdl11Definition; } @Bean public XsdSchema booksSchema() { return new SimpleXsdSchema(new ClassPathResource("book.xsd")); } }
Spring WS使用MessageSispatcherServlet处理SOAP消息。
设置ApplicationContext非常重要,否则Spring Ws将无法自动检测Spring Bean。
defaultwsdl11definition使用xsdschema公开标准wsdl。
请注意,DefaultWSDL11Definition for DefaultWSDL11Definition的Bean名称为WSDL定义URL,因此具有上述配置的WSDL URL将为http://localhost:8080/ws/bookswsdl.wsdl。
步骤9:创建名为"springbootoapexampleapplication.java"的主java类,这将具有主要方法。
package org.igi.theitroad; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootSoapExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringBootSoapExampleApplication.class, args); } }
运行应用程序
步骤10:运行应用程序在运行上面的应用程序时,我们将得到以下输出:
... ... 2016-09-16 20:30:37.597 INFO 24898 — [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2016-09-16 20:30:38.157 INFO 24898 — [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2016-09-16 20:30:38.348 INFO 24898 — [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path " 2016-09-16 20:30:38.355 INFO 24898 — [ main] o.a.j.SpringBootSoapExampleApplication : Started SpringBootSoapExampleApplication in 11.127 seconds (JVM running for 14.293)
测试WSDL URL.
步骤11:检查WSDL URL。
URL:http://localhost:8080/ws/bookswsdl.wsdl点击上述URL,我们将得到以下WSDL文件。
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="https://www.theitroad.com/xml/book" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://www.theitroad.com/xml/book" targetNamespace="https://www.theitroad.com/xml/book"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="https://www.theitroad.com/xml/book"> <xs:element name="getBookRequest"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:int" </xs:sequence> </xs:complexType> </xs:element> <xs:element name="getBookResponse"> <xs:complexType> <xs:sequence> <xs:element name="Book" type="tns:Book" </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="Book"> <xs:sequence> <xs:element name="id" type="xs:int" <xs:element name="title" type="xs:string" <xs:element name="pages" type="xs:long" </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="getBookRequest"> <wsdl:part element="tns:getBookRequest" name="getBookRequest"> </wsdl:part> </wsdl:message> <wsdl:message name="getBookResponse"> <wsdl:part element="tns:getBookResponse" name="getBookResponse"> </wsdl:part> </wsdl:message> <wsdl:portType name="BooksPort"> <wsdl:operation name="getBook"> <wsdl:input message="tns:getBookRequest" name="getBookRequest"> </wsdl:input> <wsdl:output message="tns:getBookResponse" name="getBookResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="BooksPortSoap11" type="tns:BooksPort"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" <wsdl:operation name="getBook"> <soap:operation soapAction="" <wsdl:input name="getBookRequest"> <soap:body use="literal" </wsdl:input> <wsdl:output name="getBookResponse"> <soap:body use="literal" </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="BooksPortService"> <wsdl:port binding="tns:BooksPortSoap11" name="BooksPortSoap11"> <soap:address location="http://localhost:8080/ws" </wsdl:port> </wsdl:service> </wsdl:definitions>
测试SpringSOAP Web服务
步骤11:SOAP UI上的测试应用程序在SOAP UI上使用上述WSDL文件创建一个项目并测试应用程序。
SOAP请求
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:book="https://www.theitroad.com/xml/book"> <soapenv:Header <soapenv:Body> <book:getBookRequest> <book:id>3</book:id> </book:getBookRequest> </soapenv:Body> </soapenv:Envelope>
SOAP响应
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header <SOAP-ENV:Body> <ns2:getBookResponse xmlns:ns2="https://www.theitroad.com/xml/book"> <ns2:Book> <ns2:id>3</ns2:id> <ns2:title>Learning Python</ns2:title> <ns2:pages>400</ns2:pages> </ns2:Book> </ns2:getBookResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>