运营相关个人学习springboot

Spring Boot 开发 SOAP 服务

2020-01-06  本文已影响0人  又语

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


目录


SOAP 简介

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

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

语法规则:

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


开发环境


基础示例

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

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
    <version>1.6.3</version>
</dependency>
  1. pom 文件中添加 jaxb2-maven-plugin 插件。
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>2.5.0</version>
    <executions>
        <execution>
            <id>xjc</id>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <sources>
            <source>src/main/resources/xsd</source>
        </sources>
        <outputDirectory>src/main/java</outputDirectory>
        <packageName>tutorial.spring.boot.soap.producer.generated</packageName>
        <clearOutputDir>false</clearOutputDir>
    </configuration>
</plugin>

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

完整的 pom 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>tutorial.spring.boot</groupId>
    <artifactId>spring-boot-soap-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-soap-producer</name>
    <description>Demo project for Spring Boot SOAP producer</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>2.5.0</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sources>
                        <source>src/main/resources/xsd</source>
                    </sources>
                    <outputDirectory>src/main/java</outputDirectory>
                    <packageName>tutorial.spring.boot.soap.producer.generated</packageName>
                    <clearOutputDir>false</clearOutputDir>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  1. 创建 XML Schema 定义领域模型,在 src/main/resources/xsd 目录下添加 user.xsd 文件。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:tns="http://tutorial.spring.boot/soap/produce/user"
           targetNamespace="http://tutorial.spring.boot/soap/produce/user"
           elementFormDefault="qualified">
  <xs:complexType name="User">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="birth" type="xs:date"/>
      <xs:element name="gender" type="tns:Gender"/>
    </xs:sequence>
  </xs:complexType>

  <xs:simpleType name="Gender">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Male"/>
      <xs:enumeration value="Female"/>
      <xs:enumeration value="Unknown"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="UserRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name="UserResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="user" type="tns:User"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

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"));
    }
}

说明:

注意:必须为 MessageDispatcherServletDefaultWsdl11Definition 实例指定名称,通过指定名称确定 WSDL URL。本文示例中 MessageDispatcherServlet 实例名称为 wsDefaultWsdl11Definition 实例名称为 user,因此 WSDL URL 是 http://<host>:<port>/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;
    }
}

说明:

  1. 启动应用后使用浏览器访问 http://127.0.0.1:8080/ws/user.wsdl
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://tutorial.spring.boot/soap/produce/user" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://tutorial.spring.boot/soap/produce/user" targetNamespace="http://tutorial.spring.boot/soap/produce/user">
  <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://tutorial.spring.boot/soap/produce/user">
      <xs:complexType name="User">
        <xs:sequence>
          <xs:element name="name" type="xs:string"/>
          <xs:element name="birth" type="xs:date"/>
          <xs:element name="gender" type="tns:Gender"/>
        </xs:sequence>
      </xs:complexType>
      <xs:simpleType name="Gender">
        <xs:restriction base="xs:string">
          <xs:enumeration value="Male"/>
          <xs:enumeration value="Female"/>
          <xs:enumeration value="Unknown"/>
        </xs:restriction>
      </xs:simpleType>
      <xs:element name="UserRequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="UserResponse">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="user" type="tns:User"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
  </wsdl:types>
  <wsdl:message name="UserRequest">
    <wsdl:part element="tns:UserRequest" name="UserRequest"> </wsdl:part>
  </wsdl:message>
  <wsdl:message name="UserResponse">
    <wsdl:part element="tns:UserResponse" name="UserResponse"> </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="UserPort">
    <wsdl:operation name="User">
      <wsdl:input message="tns:UserRequest" name="UserRequest"> </wsdl:input>
      <wsdl:output message="tns:UserResponse" name="UserResponse"> </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="UserPortSoap11" type="tns:UserPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="User">
      <soap:operation soapAction=""/>
      <wsdl:input name="UserRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="UserResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="UserPortService">
    <wsdl:port binding="tns:UserPortSoap11" name="UserPortSoap11">
      <soap:address location="http://127.0.0.1:8080/ws"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

从 WSDL 文件中可以看出:

  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 描述文件,执行测试。
上一篇下一篇

猜你喜欢

热点阅读