原文: https://howtodoinjava.com/spring-boot/spring-boot-soap-webservice-example/
了解如何利用 Spring Boot 的简便性来快速创建 SOAP Web 服务。 REST 和微服务每天都在流行,但是 SOAP 在某些情况下仍然有自己的地位。 在本 SpringBoot SOAP 教程中,我们将仅关注与 SpringBoot 相关的配置,以了解我们可以多么轻松地创建我们的第一个 SOAP Webservice 。
我们将构建一个简单的合同优先的 SOAP Web 服务,在其中我们将使用硬编码后端实现学生搜索功能,以进行演示。
- JDK 1.8,Eclipse,Maven – 开发环境
- SpringBoot – 基础应用程序框架
- wsdl4j – 为我们的服务发布 WSDL
- SOAP-UI – 用于测试我们的服务
- JAXB maven 插件 – 用于代码生成
为该演示创建的类和文件如下所示。
Spring Boot SOAP WS 项目结构
仅从具有Web Services
依赖关系的 SPRING 初始化器站点创建一个 spring boot 项目。 选择依赖项并提供适当的 Maven GAV 坐标后,以压缩格式下载项目。 解压缩,然后将 eclipse 中的项目导入为 maven 项目。
Spring boot 项目生成
编辑pom.xml
并将此依赖项添加到您的项目中。
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
当我们遵循合同优先的方法来开发服务时,我们需要首先为我们的服务创建域(方法和参数)。 为简单起见,我们将请求和响应都保留在相同的 XSD 中,但在实际的企业用例中,我们将有多个 XSD 相互导入以形成最终定义。
student.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="https://www.howtodoinjava.com/xml/school"
targetNamespace="https://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>
将以上文件放置在项目的resources
文件夹中。
我们将使用jaxb2-maven-plugin
有效地生成域类。 现在,我们需要将以下 Maven 插件添加到项目的pom.xml
文件的插件部分。
<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 模式文件编译为完全注解的 Java 类。
现在执行上面的 maven 插件以从 XSD 生成 Java 代码。
StudentEndpoint
类将处理对服务的所有传入请求,并将调用委派给数据存储库的finder
方法。
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 = "https://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;
}
}
这里有一些关于注解的细节:
@Endpoint
向 Spring WS 注册该类,作为处理传入 SOAP 消息的潜在候选者。- 然后,Spring WS 使用
@PayloadRoot
根据消息的名称空间和 localPart 选择处理器方法。 请注意此注解中提到的命名空间 URL 和请求载荷根请求。 @RequestPayload
表示传入的消息将被映射到方法的请求参数。@ResponsePayload
注解使 Spring WS 将返回的值映射到响应载荷。
如前所述,我们将使用硬编码的数据作为此演示的后端,让我们添加一个名为StudentRepository.java
并带有 Spring @Repository
注解的类。 它只会将数据保存在HashMap
中,并且还会提供一种称为findStudent()
的查找器方法。
阅读更多 –
@Repository
注解
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
注解的类以保存 bean 定义。
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("https://www.howtodoinjava.com/xml/school");
wsdl11Definition.setSchema(countriesSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema countriesSchema()
{
return new SimpleXsdSchema(new ClassPathResource("school.xsd"));
}
}
-
Config
类扩展了WsConfigurerAdapter
,它配置了注解驱动的 Spring-WS 编程模型。 -
MessageDispatcherServlet
– Spring-WS 使用它来处理 SOAP 请求。 我们需要向该 servlet 注入ApplicationContext
,以便 Spring-WS 找到其他 bean。 它还声明了请求的 URL 映射。 -
DefaultWsdl11Definition
使用XsdSchema
公开了标准的 WSDL 1.1。 Bean 名称studentDetailsWsdl
将是将公开的 wsdl 名称。 它可以在 http:// localhost:8080 / service / studentDetailsWsdl.wsdl 下找到。 这是在 Spring 公开合约优先的 wsdl 的最简单方法。此配置还在内部使用 WSDL 位置 servlet 转换
servlet.setTransformWsdlLocations( true )
。 如果我们看到导出的 WSDL,则soap:address
将具有localhost
地址。 同样,如果我们改为从分配给已部署机器的面向公众的 IP 地址访问 WSDL,我们将看到该地址而不是localhost
。 因此,端点 URL 根据部署环境是动态的。
使用mvn clean install
进行 maven 构建,然后使用java -jar target\spring-boot-soap-service-0.0.1-SNAPSHOT.jar
命令启动应用程序。 这将在默认端口8080
中启动一台 tomcat 服务器,并将在其中部署应用程序。
1)现在转到http://localhost:8080/service/studentDetailsWsdl.wsdl
,查看 WSDL 是否正常运行。
WSDL 已生成
2)一旦成功生成了 WSDL,就可以使用该 WSDL 在 SOAP ui 中创建一个项目并测试该应用程序。 样品请求和响应如下。
请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="https://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="https://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>
SOAP UI 示例
在上面的示例中,我们学习了使用 Spring Boot 创建 SOAP Web 服务。 我们还学习了从 WSDL 生成 Java 代码。 我们了解了处理 SOAP 请求所需的 bean。
如果您在执行上述项目时遇到任何困难,请随时发表评论。
学习愉快!
阅读更多: