本文將學習如何利用Spring boot快速建立SOAP webservice服務;java
雖然目前REST和微服務愈來愈流行,可是SOAP在某些狀況下,仍然有它的用武之地;web
在本篇 spring boot SOAP教程中,咱們會專一於和Spring boot相關的配置,感覺下在Spring Boot中,建立SOAP webservice是如何的簡便、快速;spring
本文將以一個"學生搜索"這個小功能做爲示例,演示Spring Boot中SOAP webservice的建立過程;編程
JDK 1.8, Eclipse, Maven
– 開發環境Spring-boot
– 基礎開發框架wsdl4j
– 發佈WSDLSOAP-UI
– 測試服務JAXB maven plugin
- 代碼生成本工程的代碼及文件目錄結構以下
tomcat
訪問 SPRING INITIALIZR網站,添加Web Services
依賴,輸入maven
的GAV 座標,點擊下載工程,下載完成後解壓導入IDE便可;
修改pom.xml
文件,添加Wsdl4j依賴:springboot
<dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> </dependency>
首先,咱們須要給咱們的服務建立domain(方法和參數),出於簡便考慮,我將請求和響應放在了同一個XSD文件裏,不過在實際應用開發的時候,一般須要放到多個XSD文件裏;app
建立student.xsd文件,並放到咱們工程的resources 目錄下
student.xsd框架
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.howtodoinjava.com/xml/school" targetNamespace="http://www.howtodoinjava.com/xml/school" elementFormDefault="qualified"> <xs:element name="StudentDetailsRequest"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="StudentDetailsResponse"> <xs:complexType> <xs:sequence> <xs:element name="Student" type="tns:Student"/> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="Student"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="standard" type="xs:int"/> <xs:element name="address" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema>
咱們將使用jaxb2-maven-plugin
來高效的生成domain代碼,首先須要在pom.xml
文件添加如下插件配置代碼:dom
<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>
該插件將使用 XJC
工具做爲代碼生成引擎,XJC能將XML schema 文件轉成帶註解的代碼;
如今,咱們就能夠執行以上插件生成代碼了;maven
StudentEndpoint
類會處理全部訪問該服務的請求,並委派給StudentRepository
去處理,具體代碼以下:
package com.example.howtodoinjava.springbootsoapservice; 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.howtodoinjava.xml.school.StudentDetailsRequest; import com.howtodoinjava.xml.school.StudentDetailsResponse; @Endpoint public class StudentEndpoint { private static final String NAMESPACE_URI = "http://www.howtodoinjava.com/xml/school"; private StudentRepository StudentRepository; @Autowired public StudentEndpoint(StudentRepository StudentRepository) { this.StudentRepository = StudentRepository; } @PayloadRoot(namespace = NAMESPACE_URI, localPart = "StudentDetailsRequest") @ResponsePayload public StudentDetailsResponse getStudent(@RequestPayload StudentDetailsRequest request) { StudentDetailsResponse response = new StudentDetailsResponse(); response.setStudent(StudentRepository.findStudent(request.getName())); return response; } }
對上面的幾個註解作個簡單說明(能夠和Spring MVC的Controller作個類比,有點類似):
@Endpoint
聲明用於處理SOAP消息@PayloadRoot
根據namespace和localPart映射對應的處理方法@RequestPayload
聲明進來的消息將會與該方法的參數映射@ResponsePayload
方法返回值的映射出於簡便考慮,咱們將直接在代碼裏初始化相關數據,代碼以下:
建立StudentRepository.java
,加上@Repository
註解,添加findStudent()
方法:
package com.example.howtodoinjava.springbootsoapservice; import java.util.HashMap; import java.util.Map; import javax.annotation.PostConstruct; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import com.howtodoinjava.xml.school.Student; @Component public class StudentRepository { private static final Map<String, Student> students = new HashMap<>(); @PostConstruct public void initData() { Student student = new Student(); student.setName("Sajal"); student.setStandard(5); student.setAddress("Pune"); students.put(student.getName(), student); student = new Student(); student.setName("Kajal"); student.setStandard(5); student.setAddress("Chicago"); students.put(student.getName(), student); student = new Student(); student.setName("Lokesh"); student.setStandard(6); student.setAddress("Delhi"); students.put(student.getName(), student); student = new Student(); student.setName("Sukesh"); student.setStandard(7); student.setAddress("Noida"); students.put(student.getName(), student); } public Student findStudent(String name) { Assert.notNull(name, "The Student's name must not be null"); return students.get(name); } }
添加一個帶@Configuration
註解的配置類:
package com.example.howtodoinjava.springbootsoapservice; 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 Config extends WsConfigurerAdapter { @Bean public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { MessageDispatcherServlet servlet = new MessageDispatcherServlet(); servlet.setApplicationContext(applicationContext); servlet.setTransformWsdlLocations(true); return new ServletRegistrationBean(servlet, "/service/*"); } @Bean(name = "studentDetailsWsdl") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("StudentDetailsPort"); wsdl11Definition.setLocationUri("/service/student-details"); wsdl11Definition.setTargetNamespace("http://www.howtodoinjava.com/xml/school"); wsdl11Definition.setSchema(countriesSchema); return wsdl11Definition; } @Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema(new ClassPathResource("school.xsd")); } }
WsConfigurerAdapter
類配置了註解驅動的 Spring-WS編程模式;MessageDispatcherServlet
- Spring-WS使用該類處理SOAP 請求,咱們須要把該Servlet注入ApplicationContext ,以便Spring-WS能找到其它Bean;DefaultWsdl11Definition
使用XsdSchema暴露了一個標準的的WSDL 1.1,bean的名字studentDetailsWsdl 將會做爲wsdl 暴露出去的名稱,咱們能夠經過http://localhost:8080/service/studentDetailsWsdl.wsdl
路徑訪問;使用mvn clean install
maven命名構建工程,並使用java -jar target\spring-boot-soap-service-0.0.1-SNAPSHOT.jar
命令啓動應用;
執行完以上操做後,將會以默認的8080端口啓動一個tomcat服務,本應用將部署在該服務裏;
如今咱們能夠訪問http://localhost:8080/service/studentDetailsWsdl.wsdl
路徑,確認wsdl是不是正確的:
若是咱們的wsdl沒問題的話,咱們可使用該WSDL 在SOAP ui 裏建立一個工程,並測試該應用,請求和響應示例以下:
請求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://www.howtodoinjava.com/xml/school"> <soapenv:Header/> <soapenv:Body> <sch:StudentDetailsRequest> <sch:name>Sajal</sch:name> </sch:StudentDetailsRequest> </soapenv:Body> </soapenv:Envelope>
響應
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <ns2:StudentDetailsResponse xmlns:ns2="http://www.howtodoinjava.com/xml/school"> <ns2:Student> <ns2:name>Sajal</ns2:name> <ns2:standard>5</ns2:standard> <ns2:address>Pune</ns2:address> </ns2:Student> </ns2:StudentDetailsResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
本文學習瞭如何使用Spring Boot建立SOAP webservice,同時也學習瞭如何利用wsdl生成代碼,以及Spring-WS如何處理SOAP 請求