← Назад к вопросам

Что такое SOAP WSDL?

1.7 Middle🔥 181 комментариев
#REST API и микросервисы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

SOAP и WSDL: Классические протоколы веб-сервисов

SOAP и WSDL — это фундаментальные технологии для создания веб-сервисов, которые были революционными в начале 2000-х и остаются актуальными в legacy-системах и enterprise-приложениях.

SOAP (Simple Object Access Protocol)

SOAP — это протокол обмена структурированными сообщениями на основе XML. Несмотря на название ("Simple"), SOAP довольно сложный и многоуровневый.

Структура SOAP сообщения

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <!-- Optional Header с метаинформацией -->
    <soap:Header>
        <Authentication>
            <Token>abc123xyz</Token>
        </Authentication>
    </soap:Header>
    
    <!-- Body с фактическими данными -->
    <soap:Body>
        <!-- RPC (Remote Procedure Call) стиль -->
        <GetUserResponse xmlns="http://example.com/users">
            <UserId>123</UserId>
            <UserName>John Doe</UserName>
            <Email>john@example.com</Email>
            <CreatedAt>2023-01-15</CreatedAt>
        </GetUserResponse>
    </soap:Body>
</soap:Envelope>

Запрос через SOAP

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tns="http://example.com/users">
    <soap:Body>
        <tns:GetUser>
            <tns:UserId>123</tns:UserId>
        </tns:GetUser>
    </soap:Body>
</soap:Envelope>

Применяется вдобавок к транспорту (HTTP, SMTP, FTP). Обычно используется HTTP POST:

POST /ws/userService HTTP/1.1
Host: api.example.com
Content-Type: text/xml; charset=UTF-8
SOAPAction: "http://example.com/users/GetUser"
Content-Length: 350

[XML body выше]

WSDL (Web Services Description Language)

WSDL — это язык описания веб-сервисов на XML. Это контракт между клиентом и сервером, определяющий:

  • Какие операции доступны
  • Какие параметры требуют операции
  • Какой тип данных возвращается
  • Где находится сервис (endpoint)

Структура WSDL документа

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:tns="http://example.com/users"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             targetNamespace="http://example.com/users">
    
    <!-- 1. TYPES: Определение структуры данных -->
    <types>
        <xsd:schema targetNamespace="http://example.com/users">
            <xsd:element name="User">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="id" type="xsd:long"/>
                        <xsd:element name="name" type="xsd:string"/>
                        <xsd:element name="email" type="xsd:string"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
            
            <xsd:element name="GetUserRequest">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="userId" type="xsd:long"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:schema>
    </types>
    
    <!-- 2. MESSAGES: Входные и выходные сообщения -->
    <message name="GetUserRequest">
        <part name="body" element="tns:GetUserRequest"/>
    </message>
    
    <message name="GetUserResponse">
        <part name="body" element="tns:User"/>
    </message>
    
    <!-- 3. PORT TYPE: Определение операций (интерфейс) -->
    <portType name="UserServicePortType">
        <operation name="GetUser">
            <input message="tns:GetUserRequest"/>
            <output message="tns:GetUserResponse"/>
            <fault message="tns:FaultMessage"/>
        </operation>
    </portType>
    
    <!-- 4. BINDING: Как операции транспортируются (протокол) -->
    <binding name="UserServiceBinding" type="tns:UserServicePortType">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        
        <operation name="GetUser">
            <soap:operation soapAction="http://example.com/users/GetUser"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    
    <!-- 5. SERVICE: Конкретное развёртывание сервиса (endpoint) -->
    <service name="UserService">
        <port name="UserServicePort" binding="tns:UserServiceBinding">
            <soap:address location="http://api.example.com/ws/userService"/>
        </port>
    </service>
</definitions>

Java реализация с JAX-WS

Java имеет встроенную поддержку SOAP через JAX-WS (Java API for XML Web Services):

Создание SOAP сервера

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

@WebService(
    name = "UserService",
    portName = "UserServicePort",
    serviceName = "UserService",
    targetNamespace = "http://example.com/users"
)
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)  // Document style (WSDL описывает структуру)
public class UserService {
    
    @WebMethod(operationName = "GetUser")
    public User getUser(Long userId) {
        // Логика здесь
        return new User(userId, "John Doe", "john@example.com");
    }
    
    @WebMethod(operationName = "CreateUser")
    public Long createUser(String name, String email) {
        // Сохранение в БД
        return 1L;
    }
}

// Аннотированный класс данных
@XmlRootElement(name = "User")
public class User {
    @XmlElement
    private Long id;
    
    @XmlElement
    private String name;
    
    @XmlElement
    private String email;
    
    // Конструкторы, геттеры, сеттеры
    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
}

Запуск SOAP сервера

import javax.xml.ws.Endpoint;

public class UserServicePublisher {
    public static void main(String[] args) {
        // Публикуем сервис на http://localhost:8080/ws/userService
        UserService service = new UserService();
        String endpointAddress = "http://localhost:8080/ws/userService";
        Endpoint.publish(endpointAddress, service);
        
        System.out.println("UserService published at " + endpointAddress);
        System.out.println("WSDL available at " + endpointAddress + "?wsdl");
    }
}

Клиент SOAP

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.URL;

public class UserServiceClient {
    public static void main(String[] args) throws Exception {
        // Загружаем WSDL
        URL wsdlLocation = new URL("http://localhost:8080/ws/userService?wsdl");
        QName serviceName = new QName(
            "http://example.com/users",
            "UserService"
        );
        
        // Создаём сервис
        Service service = Service.create(wsdlLocation, serviceName);
        
        // Получаем port (proxy)
        QName portName = new QName(
            "http://example.com/users",
            "UserServicePort"
        );
        UserService port = service.getPort(portName, UserService.class);
        
        // Вызываем операцию (идентично локальному вызову!)
        User user = port.getUser(123L);
        System.out.println(user.getName());
    }
}

С Spring (современный подход)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.ws.config.annotation.EnableWs;

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

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;

@Endpoint
public class UserEndpoint {
    
    @PayloadRoot(
        namespace = "http://example.com/users",
        localPart = "GetUserRequest"
    )
    @ResponsePayload
    public GetUserResponse getUser(@RequestPayload GetUserRequest request) {
        User user = new User(request.getUserId(), "John", "john@example.com");
        GetUserResponse response = new GetUserResponse();
        response.setUser(user);
        return response;
    }
}

SOAP vs REST

КритерийSOAPREST
ПротоколXML-RPC (сложный)Стиль архитектуры (простой)
Размер сообщенийБольшой (XML overhead)Компактный (JSON)
КэшированиеСложно (POST всегда)Встроено (GET кэшируется)
СложностьВысокая (WSDL, XSD)Низкая (договоренность)
EnterpriseДа (WS-Security, WS-RM)Нет встроено
ИспользованиеLegacy системы, banksСовременные API, мобильные
Скорость разработкиМедленнееБыстрее

Современная ситуация

SOAP всё ещё используется:

  • Enterprise системы и банки (надежность, WS-*)
  • Legacy приложения
  • Системы с жёсткими требованиями к контрактам

REST доминирует:

  • Современные API
  • Мобильные приложения
  • Микросервисы
  • Публичные API

Но в Java, особенно в enterprise, знание SOAP/WSDL всё ещё требуется.