Spring Boot 开发 SOAP 服务

本文介绍 Spring Boot 2 开发 SOAP 服务的方法。


目录

  • SOAP 简介
  • 开发环境
  • 基础示例
  • 总结

SOAP 简介

SOAP,Simple Object Access Protocol,简单对象访问协议,是一种基于 XML 实现网络中数据交换的通信协议。

一条 SOAP 消息就是一个普通的 XML 文档,包含以下元素:

  • 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
  • 可选的 Header 元素,包含头部信息
  • 必需的 Body 元素,包含所有的调用和响应信息
  • 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息

语法规则:

  • SOAP 消息必须用 XML 来编码
  • SOAP 消息必须使用 SOAP Envelope 命名空间
  • SOAP 消息必须使用 SOAP Encoding 命名空间
  • SOAP 消息不能包含 DTD 引用
  • SOAP 消息不能包含 XML 处理指令

SOAP 是 Web Service 三要素之一,是用来描述传递信息的格式,另外两个元素:

  • WSDL,Web Services Description Language,描述如何访问具体接口。
  • UDDI,Universal Description Discovery and Integration,管理、分发和查询 Web Service。

开发环境

  • Oracle JDK 1.8.0_201
  • Apache Maven 3.6.0
  • IntelliJ IDEA (Version 2018.3.3)

基础示例

  1. 创建 Spring Boot 工程,参考:IntelliJ IDEA 创建 Spring Boot 工程。

  2. pom 文件中添加 spring-boot-starter-web-serviceswsdl4j 依赖。


    org.springframework.boot
    spring-boot-starter-web-services


    wsdl4j
    wsdl4j
    1.6.3

  1. pom 文件中添加 jaxb2-maven-plugin 插件。

    org.codehaus.mojo
    jaxb2-maven-plugin
    2.5.0
    
        
            xjc
            
                xjc
            
        
    
    
        
            src/main/resources/xsd
        
        src/main/java
        tutorial.spring.boot.soap.producer.generated
        false
    

jaxb2-maven-plugin 能够实现 Java 类和 XML Schema 间的转换,配置说明:

  • sources:xsd 文件目录
  • outputDirectory:生成 Java 类文件的根目录
  • packageName:生成 Java 类文件的包路径
  • clearOutputDir:重新生成前是否需要清空目录

完整的 pom 文件如下:



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.2.2.RELEASE
        
    
    tutorial.spring.boot
    spring-boot-soap-producer
    0.0.1-SNAPSHOT
    spring-boot-soap-producer
    Demo project for Spring Boot SOAP producer

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-web-services
        
        
            wsdl4j
            wsdl4j
            1.6.3
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
                org.codehaus.mojo
                jaxb2-maven-plugin
                2.5.0
                
                    
                        xjc
                        
                            xjc
                        
                    
                
                
                    
                        src/main/resources/xsd
                    
                    src/main/java
                    tutorial.spring.boot.soap.producer.generated
                    false
                
            
        
    


  1. 创建 XML Schema 定义领域模型,在 src/main/resources/xsd 目录下添加 user.xsd 文件。

  
    
      
      
      
    
  

  
    
      
      
      
    
  

  
    
      
        
      
    
  

  
    
      
        
      
    
  

Web Service 领域模型定义在 XML Schema(XSD) 文件中,Spring-WS 会自动导出 WSDL。

  1. 执行 mvn compile 生成 Java 类文件,生成文件:
|-- src
     |-- main
          |-- java
              |-- META-INF.JAXB
                  |-- episode_xjc.xjb
              |-- tutorial.spring.boot.soap.producer
                  |-- generated
                      |-- Gender.java
                      |-- ObjectFactory.java
                      |-- package-info.java
                      |-- User.java
                      |-- UserRequest.java
                      |-- UserResponse.java
  1. 创建 Web Service 配置类。
package tutorial.spring.boot.soap.producer.config;

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.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;

@EnableWs
@Configuration
public class WebServiceConfig {

    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean(name = "user")
    public Wsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("UserPort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://tutorial.spring.boot/soap/produce/user");
        wsdl11Definition.setSchema(schema);
        return wsdl11Definition;
    }

    @Bean
    public XsdSchema userSchema() {
        return new SimpleXsdSchema(new ClassPathResource("xsd/user.xsd"));
    }
}

说明:

  • Spring WS 使用 MessageDispatcherServlet 处理 SOAP 消息,所以创建 Web Service 配置需要新建一个 MessageDispatcherServlet 实例,并将应用上下文 ApplicationContext 注入该实例。
  • MessageDispatcherServlet 实例命名为 messageDispatcherServlet 并不会替换 Spring Boot 默认的 DispatcherServlet bean。
  • DefaultWsdl11Definition 使用 XSD Schema 暴露标准的 WSDL 1.1。

注意:必须为 MessageDispatcherServletDefaultWsdl11Definition 实例指定名称,通过指定名称确定 WSDL URL。本文示例中 MessageDispatcherServlet 实例名称为 wsDefaultWsdl11Definition 实例名称为 user,因此 WSDL URL 是 http://:/ws/user.wsdl

  1. 创建服务端点:定义一个 @Endpoint 注解的 POJO 类处理传入的 SOAP 请求。
package tutorial.spring.boot.soap.producer.controller;

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 tutorial.spring.boot.soap.producer.generated.Gender;
import tutorial.spring.boot.soap.producer.generated.User;
import tutorial.spring.boot.soap.producer.generated.UserRequest;
import tutorial.spring.boot.soap.producer.generated.UserResponse;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import java.time.LocalDate;

@Endpoint
public class UserController {

    private static final String NAMESPACE_URI = "http://tutorial.spring.boot/soap/produce/user";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "UserRequest")
    @ResponsePayload
    public UserResponse getUser(@RequestPayload UserRequest request) throws DatatypeConfigurationException {
        UserResponse response = new UserResponse();
        User user = new User();
        String name = request.getName();
        user.setName(name);
        switch (name) {
            case "Mike":
                user.setBirth(
                        DatatypeFactory.newInstance().newXMLGregorianCalendar(
                                LocalDate.of(2000, 1, 1).toString()
                        )
                );
                user.setGender(Gender.MALE);
                break;
            case "Ketty":
                user.setBirth(
                        DatatypeFactory.newInstance().newXMLGregorianCalendar(
                                LocalDate.of(2010, 12, 31).toString()
                        )
                );
                user.setGender(Gender.FEMALE);
                break;
            default:
                user.setGender(Gender.UNKNOWN);
                break;
        }
        response.setUser(user);
        return response;
    }
}

说明:

  • @Endpoint
    注解类将被注册到 Spring WS 中用于处理传入的 SOAP 消息。
  • @PayloadRoot
    Spring WS 通过此注解查找匹配消息 namespacelocalPart 的处理方法。
  • @RequestPayload
    标识传入的消息将被映射到方法的哪个入参。
  • @ResponsePayload
    此注解标识 Spring WS 将方法返回值映射到响应负载。
  1. 启动应用后使用浏览器访问 http://127.0.0.1:8080/ws/user.wsdl

  
    
      
        
          
          
          
        
      
      
        
          
          
          
        
      
      
        
          
            
          
        
      
      
        
          
            
          
        
      
    
  
  
     
  
  
     
  
  
    
       
       
    
  
  
    
    
      
      
        
      
      
        
      
    
  
  
    
      
    
  

从 WSDL 文件中可以看出:

  • 接口名称(wsdl:operation):User
  • 输入参数(wsdl:input):UserRequest
  • 输出参数(wsdl:output):UserResponse
  • 接口地址(soap:address):http://127.0.0.1:8080/ws
  1. 使用 Soap UI 工具测试。

总结

Spring Boot 开发 SOAP 服务的步骤:

  1. 创建 Spring Boot 应用,添加 spring-boot-starter-web-serviceswsdl4j 依赖及 jaxb2-maven-plugin 插件;
  2. 创建 xsd 文件;
  3. 执行 mvn compile 生成由 xsd 文件生产 Java 类;
  4. 创建 Web Service 配置类;
  5. 创建业务服务类;
  6. 启动应用,通过浏览器查看 wsdl 描述文件,执行测试。

你可能感兴趣的:(Spring Boot 开发 SOAP 服务)