知識庫 / Spring / Spring Boot RSS 訂閱

使用 Spring 創建 SOAP Web 服務

Spring Boot
HongKong
4
01:26 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將學習如何使用 Spring Boot Starter Web Services 創建一個基於 SOAP 的 Web 服務。

2. SOAP Web 服務

簡而言之,Web 服務是一種機器對機器、平台無關的服務,它允許通過網絡進行通信。

SOAP 是一種消息協議。消息(請求和響應)是 基於 HTTP 的 XML 文檔XML 契約由 WSDL(Web Services Description Language)定義。 它提供了一組規則,用於定義消息、綁定、操作和服務的定位。

SOAP 中使用的 XML 可能會變得非常複雜。 因此,最好使用像 JAX-WS 或 Spring 這樣的框架與 SOAP 一起使用,正如本教程中看到的。

3. 採用合同優先開發風格

在創建 Web 服務時,存在兩種可能的方法:合同末先合同優先。 當我們採用合同優先方法時,我們首先從 Java 代碼開始,然後從類生成 Web 服務合同 (WSDL)。 使用合同優先方法時,我們首先從 WSDL 合同開始,然後從該合同生成 Java 類。

Spring-WS 僅支持合同優先開發風格。

4. 設置 Spring Boot 項目

我們將創建一個 Spring Boot 項目,其中定義我們的 SOAP WS 服務器。

4.1. Maven 依賴

讓我們首先添加 `spring-boot-starter-parent 到我們的項目:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
</parent>

接下來,我們添加以下依賴項: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>
</dependency>

4.2. XSD 文件

合同優先方法要求我們首先定義服務的領域(方法和參數)。我們將使用 Spring-WS 自動導出的 XML 模式文件(XSD)作為 WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.baeldung.com/springsoap/gen"
           targetNamespace="http://www.baeldung.com/springsoap/gen" elementFormDefault="qualified">

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

    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="population" type="xs:int"/>
            <xs:element name="capital" type="xs:string"/>
            <xs:element name="currency" type="tns:currency"/>
        </xs:sequence>
    </xs:complexType>

    <xs:simpleType name="currency">
        <xs:restriction base="xs:string">
            <xs:enumeration value="GBP"/>
            <xs:enumeration value="EUR"/>
            <xs:enumeration value="PLN"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

在本文件中,我們可以看到 getCountryRequest Web 服務請求的格式。 我們將其定義為接受一個類型為 string 的參數。

接下來,我們將定義響應的格式,該響應包含一個類型為 country 的對象。

最後,我們可以看到在 country 對象中使用的 currency 對象。

4.3. 生成領域 Java 類

現在我們將從前一節中定義的 XSD 文件生成 Java 類。 jaxb2-maven-plugin 將在構建期間自動執行此操作。 該插件使用 XJC 工具作為代碼生成引擎。 XJC 將 XSD 模式文件編譯成帶有完整註釋的 Java 類。

讓我們在 pom.xml 中添加和配置插件:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jaxb2-maven-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
        <execution>
            <id>xjc</id>
            <goals>
                <goal>xjc</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <sources>
            <source>src/main/resources/countries.xsd</source>
        </sources>
        <outputDirectory>src/main/java</outputDirectory>
        <clearOutputDir>false</clearOutputDir>
    </configuration>
</plugin>

我們注意到以下兩個重要配置:

  • <source>src/main/resources/countries.xsd</source>; – XSD 文件的位置
  • <outputDirectory>src/main/java</outputDirectory>; – 我們希望生成的 Java 代碼位於此處

要生成 Java 類,我們可以使用來自 Java 安裝的 XJC 工具。在我們的 Maven 項目中,這更加簡單,因為 類將在常規 Maven 構建期間自動生成

mvn compile

4.4. 添加 SOAP Web 服務端點

該 SOAP Web 服務端點類將處理所有針對服務的傳入請求。它將啓動處理並返回響應。

在定義此端點之前,我們將創建一個 國家 存儲庫,以向 Web 服務提供數據:

@Component
public class CountryRepository {

    private static final Map<String, Country> countries = new HashMap<>();

    @PostConstruct
    public void initData() {
        // initialize countries map
    }

    public Country findCountry(String name) {
        return countries.get(name);
    }
}

接下來,我們將配置端點。

@Endpoint
public class CountryEndpoint {

    private static final String NAMESPACE_URI = "http://www.baeldung.com/springsoap/gen";

    private CountryRepository countryRepository;

    @Autowired
    public CountryEndpoint(CountryRepository countryRepository) {
        this.countryRepository = countryRepository;
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
    @ResponsePayload
    public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
        GetCountryResponse response = new GetCountryResponse();
        response.setCountry(countryRepository.findCountry(request.getName()));

        return response;
    }
}

請注意以下幾點:

  • @Endpoint – 將類註冊為 Spring WS 中的 Web Service Endpoint
  • @PayloadRoot – 定義處理方法,根據 namespacelocalPart 屬性
  • @ResponsePayload – 指示該方法返回一個值,用於映射到響應 payload
  • @RequestPayload – 指示該方法接受一個參數,用於從傳入的請求中映射

4.5. Spring消息分發 servlet配置 Bean

現在,讓我們創建一個用於接收請求的 Spring 消息分發 servlet 配置類:

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    // bean definitions
}

@EnableWs 啓用 Spring Boot 應用程序中的 SOAP Web Service 功能。WebServiceConfig 類繼承了 WsConfigurerAdapter 基類,該類配置了基於註解的 Spring-WS 編程模型。

讓我們創建一個MessageDispatcherServlet,用於處理 SOAP 請求:

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

我們將設置注入的 ApplicationContext 對象,以便 Spring-WS 可以找到其他 Spring Bean。

我們還將啓用 WSDL 位置 Servlet 轉換。 這將轉換 soap:address 元素的 location 屬性,以便它反映傳入請求的 URL。

最後,我們將創建一個 DefaultWsdl11Definition 對象。 這會使用 XsdSchema 暴露一個標準 WSDL 1.1。 WSDL 名稱將與 Bean 名稱相同:

@Bean(name = "countries")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("CountriesPort");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setTargetNamespace("http://www.baeldung.com/springsoap/gen");
    wsdl11Definition.setSchema(countriesSchema);
    return wsdl11Definition;
}

@Bean
public XsdSchema countriesSchema() {
    return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
}

5. 測試 SOAP 項目

項目配置完成後,我們準備開始測試。

5.1. 構建和運行項目

可以創建WAR文件並部署到外部應用程序服務器。 相比之下,我們將使用Spring Boot,這是一種更快、更簡單的啓動和運行應用程序的方式。

首先,我們將添加以下類以使應用程序可執行:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

請注意,我們沒有使用任何 XML 文件(如 web.xml)來創建這個應用程序。 整個應用程序都是純 Java 實現。

現在,我們準備好構建和運行應用程序:

mvn spring-boot:run

為了檢查應用程序是否正常運行,我們可以通過以下 URL 打開 WSDL:http://localhost:8080/ws/countries.wsdl

5.2. 測試 SOAP 請求

為了測試請求,我們將創建一個名為 request.xml 的文件:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:gs="http://www.baeldung.com/springsoap/gen">
    <soapenv:Header/>
    <soapenv:Body>
        <gs:getCountryRequest>
            <gs:name>Spain</gs:name>
        </gs:getCountryRequest>
    </soapenv:Body>
</soapenv:Envelope>

為了將請求發送到我們的測試服務器,我們可以使用外部工具,例如 SoapUI 或 Google Chrome 擴展 Wizdler。 另一種方法是在我們的 shell 中運行以下命令:

curl --header "content-type: text/xml" -d @request.xml http://localhost:8080/ws

生成的響應可能不易閲讀,因為它缺少縮進或換行。

要查看其格式,我們可以將其複製粘貼到我們的 IDE 或其他工具中。 如果我們安裝了 xmllib2, 我們可以將 curl 命令的輸出通過管道發送到 xmllint

curl [command-line-options] | xmllint --format -

響應應包含關於西班牙的信息:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
    <ns2:getCountryResponse xmlns:ns2="http://www.baeldung.com/springsoap/gen">
        <ns2:country>
            <ns2:name>Spain</ns2:name>
            <ns2:population>46704314</ns2:population>
            <ns2:capital>Madrid</ns2:capital>
            <ns2:currency>EUR</ns2:currency>
        </ns2:country>
    </ns2:getCountryResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

6. 結論

在本文中,我們學習瞭如何使用 Spring Boot 創建 SOAP Web 服務。我們還演示瞭如何從 XSD 文件生成 Java 代碼。最後,我們配置了處理 SOAP 請求所需的 Spring Bean。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.