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>

