Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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
| Критерий | SOAP | REST |
|---|---|---|
| Протокол | 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 всё ещё требуется.