本文将学习如何利用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 请求