Spring Boot SOAP Web 服务示例
原文: https://howtodoinjava.com/spring-boot/spring-boot-soap-webservice-example/
了解如何利用 Spring Boot 的简便性来快速创建 SOAP Web 服务。 REST 和微服务每天都在流行,但是 SOAP 在某些情况下仍然有自己的地位。 在本 SpringBoot SOAP 教程中,我们将仅关注与 SpringBoot 相关的配置,以了解我们可以多么轻松地创建我们的第一个 SOAP Webservice 。
我们将构建一个简单的合同优先的 SOAP Web 服务,在其中我们将使用硬编码后端实现学生搜索功能,以进行演示。
1. 技术栈
- JDK 1.8,Eclipse,Maven – 开发环境
- SpringBoot – 基础应用程序框架
- wsdl4j – 为我们的服务发布 WSDL
- SOAP-UI – 用于测试我们的服务
- JAXB maven 插件 – 用于代码生成
2. 项目结构
为该演示创建的类和文件如下所示。
Spring Boot SOAP WS 项目结构
3. 创建 Spring Boot 项目
仅从具有Web Services
依赖关系的 SPRING 初始化器站点创建一个 spring boot 项目。 选择依赖项并提供适当的 Maven GAV 坐标后,以压缩格式下载项目。 解压缩,然后将 eclipse 中的项目导入为 maven 项目。
Spring boot 项目生成
添加 Wsdl4j 依赖关系
编辑pom.xml
并将此依赖项添加到您的项目中。
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
4. 创建 SOAP 域模型并生成 Java 代码
当我们遵循合同优先的方法来开发服务时,我们需要首先为我们的服务创建域(方法和参数)。 为简单起见,我们将请求和响应都保留在相同的 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
文件夹中。
将 XSD 的 JAXB maven 插件添加到 Java 对象生成
我们将使用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 代码。
5. 创建 SOAP Web 服务端点
StudentEndpoint
类将处理对服务的所有传入请求,并将调用委派给数据存储库的finder
方法。
package com.example.howtodoinjava.springboot<span class="highlight">soap</span>service;
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.springboot<span class="highlight">soap</span>service;
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);
}
}
6. 添加 SOAP Web 服务配置 Bean
创建带有@Configuration
注解的类以保存 bean 定义。
package com.example.howtodoinjava.springboot<span class="highlight">soap</span>service;
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 根据部署环境是动态的。
7. Spring Boot SOAP Web 服务演示
使用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 中创建一个项目并测试该应用程序。 样品请求和响应如下。
请求:
<<span class="highlight">soap</span>env:Envelope xmlns:<span class="highlight">soap</span>env="http://schemas.xml<span class="highlight">soap</span>.org/<span class="highlight">soap</span>/envelope/" xmlns:sch="https://www.howtodoinjava.com/xml/school">
<<span class="highlight">soap</span>env:Header/>
<<span class="highlight">soap</span>env:Body>
<sch:StudentDetailsRequest>
<sch:name>Sajal</sch:name>
</sch:StudentDetailsRequest>
</<span class="highlight">soap</span>env:Body>
</<span class="highlight">soap</span>env:Envelope>
响应:
<<span class="highlight">SOAP</span>-ENV:Envelope xmlns:<span class="highlight">SOAP</span>-ENV="http://schemas.xml<span class="highlight">soap</span>.org/<span class="highlight">soap</span>/envelope/">
<<span class="highlight">SOAP</span>-ENV:Header/>
<<span class="highlight">SOAP</span>-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>
</<span class="highlight">SOAP</span>-ENV:Body>
</<span class="highlight">SOAP</span>-ENV:Envelope>
SOAP UI 示例
8. 总结
在上面的示例中,我们学习了使用 Spring Boot 创建 SOAP Web 服务。 我们还学习了从 WSDL 生成 Java 代码。 我们了解了处理 SOAP 请求所需的 bean。