soap Samouczek
Pierwsze kroki z mydłem
Szukaj…
Uwagi
Ta sekcja zawiera przegląd tego, czym jest mydło i dlaczego deweloper może chcieć go używać.
Powinien również wymieniać wszelkie duże tematy w mydle i link do powiązanych tematów. Ponieważ Dokumentacja dotycząca mydła jest nowa, może być konieczne utworzenie początkowych wersji tych pokrewnych tematów.
Wersje
Wersja | Data wydania |
---|---|
1.1 | 2000-05-08 |
1.2 | 2003-06-24 |
Informacje ogólne
SOAP to skrót od Simple Object Access Protocol, który definiuje protokół używany do wymiany danych za pośrednictwem zdalnego wywoływania procedur (RPC) z innymi usługami lub klientami SOAP. Jest dostępny w dwóch wersjach:
SOAP 1.2 dezaktualizuje SOAP 1.1, dlatego zaleca się używanie SOAP 1.2, jeśli to możliwe.
Często jest oparty na HTTP / S, a rzadko na SMTP lub FTP, choć obsługuje go zgodnie z protokołem. Chociaż HTTP jest często używany jako podstawowy protokół transportowy, SOAP używa tylko jego ograniczonego podzbioru. Do wysyłania żądań opiera się prawie całkowicie na operacji POST
HTTP. Wywołania GET
są teoretycznie możliwe od 1.2, chociaż dokument musi zostać przekazany jako parametr URI, a zatem może przekraczać granicę około 3000 znaków, która jest odrzucana przez większość ram. Ponadto ustawienia związane z bezpieczeństwem są zwykle definiowane w specjalnym nagłówku SOAP.
Chociaż SOAP i REST są nazywane usługami internetowymi, z natury są bardzo różne. Niektóre platformy rozróżniają WS (dla usług opartych na SOAP) i RS (dla usług opartych na REST).
Poniższa tabela zawiera krótki przegląd różnic między oboma typami usług internetowych.
Aspekt | MYDŁO | ODPOCZYNEK |
---|---|---|
Standard | SOAP , WSDL | Brak standardu, tylko styl architektoniczny |
Adresowanie zasobów | Pośrednio przez operacje SOAP | poprzez unikalne identyfikatory zasobów (URI) |
Obsługa błędów | Komunikat o błędzie SOAP | Kody odpowiedzi na błąd HTTP i opcjonalnie treść odpowiedzi |
Reprezentacja danych | XML | wszystkie dostępne kodowania w HTTP |
Użycie HTTP | Jako protokół transportowy | Działania na zasobach (CRUD) odwzorowane na metody HTTP (GET, POST, PUT, DELETE, ...) |
Wsparcie transakcyjne | przez nagłówek SOAP | modelując transakcję jako zasób |
Stan | Stanowy (działanie SOAP jest częścią aplikacji) | Bezstanowy (samodzielne żądania) |
Odkrycie usługi | UDDI / WSDL | W rzeczywistości żaden; Start-URI interfejsu API powinien jednak zwrócić listę podrzędnych interfejsów API |
metoda | Wewnątrz ciała SOAP | Metoda HTTP |
Argumenty metod | Zdefiniowane przez schemat XML w WSDL | Albo przez nagłówki HTTP, albo ścieżkę / zapytanie lub parametry macierzy w URI |
Zmiana stanu | Trudne do ustalenia jako nie bezpośrednio oparte na danych | Następne wywołanie URI |
Wsparcie buforowania | Buforowanie często nie jest pożądane, | Prosty zgodnie z definicją HTTP |
MYDŁO
Żądania SOAP składają się z obwiedni SOAP, która musi zawierać element body i może zawierać opcjonalny element nagłówka. Element nagłówka służy do przekazywania pewnych konfiguracji do usługi, np. WS-Security może zdefiniować, że wiadomość jest szyfrowana lub WS-Coordination / WS-Transaction może zdefiniować, że komunikat musi być wykonany w ramach transakcji.
Proste żądania SOAP 1.2 przez HTTP, które dodają dwie wartości, mogą wyglądać następująco:
POST /calculator HTTP/1.1
Host: http://example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 224
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<m:AddValues xmlns:m="http://example.org/calculator">
<m:FirstValue>1</m:FirstValue>
<m:SecondValue>2</m:SecondValue>
</m:AddValues>
</env:Body>
</env:Envelope>
Odpowiedź na powyższe przykładowe żądanie może wyglądać następująco
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 329
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/calculator">
<m:AddValuesResponse>
<m:Result>3</m:Result>
</m:AddValuesResponse>
</soap:Body>
</soap:Envelope>
W powyższym przykładzie zdefiniowano żądanie, które AddValues
metodę AddValues
z dwoma argumentami, FirstValue
ustawiono na 1
a SecondValue
ustawiono na 2
. Żądanie spowodowało wykonanie tej metody na zdalnym serwerze SOAP, który w wyniku tego obliczył wartość 3
która jest zawarta w osobnym elemencie odpowiedzi, który zgodnie z konwencją jest często wywoływaną nazwą metody i ciągiem Response
więc każdy, kto jest sprawdzając odpowiedź można stwierdzić, że jest to odpowiedź na poprzednie wywołanie metody AddValue
.
Różnice między SOAP 1.1 a 1.2
SOAP 1.2 zezwala na inne protokoły transportowe niż HTTP, pod warunkiem, że protokół obsługuje strukturę powiązań.
SOAP 1.1 oparty jest na XML 1.0, natomiast 1.2 oparty jest na XML Infoset, który pozwala na serializację komunikatów SOAP za pomocą innych serializatorów niż domyślny serializator XML 1.0 używany przez SOAP 1.1. Pozwala to np. Na serializację wiadomości jako wiadomości binarnych, a tym samym zapobiega narzutowi natury wiadomości XML. Ponadto mechanizm serializacji stosowanego protokołu bazowego można określić za pomocą powiązania danych.
Aspekt interoperacyjności został również wzmocniony przez SOAP 1.2 poprzez zdefiniowanie bardziej szczegółowego modelu przetwarzania niż jego poprzednik, co wyeliminowało wiele możliwości interpretacji. SOAP z interfejsem API załączników (SAAJ), który pozwala na obsługę komunikatów SOAP 1.1 i 1.2, pomógł wielu implementatorom frameworka w przetwarzaniu i tworzeniu komunikatów.
W3C opublikowało krótki przegląd głównych zmian między SOAP 1.1 a 1.2
Interoperacyjność usług sieciowych
Interoperacyjność usług sieciowych (znana również jako WS-I) jest wytyczną dotyczącą interoperacyjności zarządzaną przez niektóre dobrze znane przedsiębiorstwa, takie jak IBM, Microsoft, Oracle i HP, aby wymienić tylko kilka. Te wytyczne między innymi zalecają stosowanie tylko jednego elementu głównego w treści SOAP, nawet jeśli SOAP pozwala na umieszczenie wielu elementów w treści.
WS-I składa się z
- Profil podstawowy WS-I aka WSI-BP
- Podstawowy profil bezpieczeństwa WS-I
- Prosty profil wiązania mydła
WSI-BP jest dostępny w 4 różnych wersjach v1.0 (2004) , v1.1 (2006) , v1.2 (2010) , v2.0 (2010) i definiuje wytyczne dotyczące interoperacyjności dla podstawowych specyfikacji usług sieciowych, takich jak SOAP, WSDL i UDDI. Za pomocą języka WSDL (Web Services Description Language) usługi SOAP mogą opisywać obsługiwane operacje i metody w spójnym zestawie z innymi punktami końcowymi. WSI-BP wykorzystuje WSDL do zdefiniowania węższego zestawu, a następnie zdefiniowałby pełny schemat WSDL lub SOAP, a tym samym eliminuje niejasności w samej specyfikacji, a tym samym poprawia interoperacyjność między punktami końcowymi.
WSDL
Aby zareklamować dostępne operacje SOAP, ich parametry, a także odpowiednie punkty końcowe, które należy wywołać u klientów, używany jest kolejny dokument oparty na języku XML, zwany w skrócie Web Services Description Language
lub WSDL.
WSDL opisuje punkt końcowy usługi, powiązanie komunikatów SOAP z operacjami, interfejs operacji oraz ich typy z klientami. WSDL, podobnie jak SOAP, jest dostępny w 2 wersjach, które różnią się nieco składnią, choć wyrażają prawie taką samą semantykę dla klienta.
WSDL 1.1
Opis WSDL 1.1 zawiera service
, binding
, portType
i sekcję message
. Może dodatkowo importować lub definiować schematy w pliku WSDL, co można zobaczyć w przykładowym pliku WSDL, który odpowiada próbce kalkulatora pokazanej powyżej:
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:calc="http://example.org/calculator"
xmlns:tns="http://example.org/calculatorService"
targetNamespace="http://example.org/calculatorService">
<!--
Abstract type definitions
-->
<wsdl:types>
<!--
<xs:schema>
<xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
</xs:schema>
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/calculator"
targetNamespace="http://example.org/calculator"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<xs:element name="AddValuesRequest" type="tns:AddValuesType" />
<xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />
<xs:complexType name="AddValuesType">
<xs:sequence>
<xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
<xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="AddValuesResponseType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Result" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:attribute name="Timestamp" type="xs:dateTime" />
<xs:element name="CalculationFailure">
<xs:complexType>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:int" />
<xs:element name="Reason" type="xs:string" />
</xs:sequence>
<xs:attribute ref="tns:Timestamp" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<!--
Abstract message definitions
-->
<wsdl:message name="AddValuesRequest">
<wsdl:part name="in" element="calc:AddValuesRequest" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="out" element="calc:AddValuesResponse" />
</wsdl:message>
<wsdl:message name="CalculationFault">
<wsdl:part name="fault" element="calc:CalculationFailure" />
</wsdl:message>
<!--
Abstract portType / interface definition
-->
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation name="AddValues">
<wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
<wsdl:input message="tns:AddValuesRequest" />
<wsdl:output message="tns:AddValuesResponse" />
<wsdl:fault name="CalculationFault" message="tns:CalculationFault" />
</wsdl:operation>
</wsdl:portType>
<!--
Concrete binding definition
-->
<wsdl:binding name="CalculatorBinding" type="tns:CalculatorEndpoint">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="AddValues">
<soap:operation soapAction="http://example.org/calculator/AddValuesMessage" />
<wsdl:input>
<soap:body parts="in" use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body parts="out" use="literal" />
</wsdl:output>
<wsdl:fault name="CalculationFault">
<soap:fault name="CalculationFault" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<!--
Concrete service definition
-->
<wsdl:service name="CalculatorService">
<wsdl:port name="CalculatorServicePort" binding="tns:CalculatorBinding">
<soap:address location="http://localhost:8080/services/calculator" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Sekcja service
określa konkretne punkty końcowe, w których usługa będzie nasłuchiwała nadchodzących żądań. Sekcja binding
wiąże operację z konkretnym stylem i określa, jakiego formatu wiadomości oczekuje serwer lub klient może się spodziewać.
Sekcja abstrakcyjna składa się z bloku portType
, który definiuje operacje oferowane przez usługę i które komunikaty są wymieniane. Komunikaty są określone w swoich blokach i połączone z typami schematów, których argumentami są i zwracane wartości. Wiadomości mogą zadeklarować parametry lub wartości zwracanych się in
, out
lub inout
. Podczas gdy pierwsze dwa są dość łatwe do uchwycenia, drugie naśladuje zachowanie argumentów przekazywanych przez referencję. Ponieważ funkcja pass-by-ref nie jest obsługiwana w niektórych językach, efekt ten jest często symulowany przez niektóre programy obsługi.
WSDL 2.0
Ten sam kalkulator można opisać w WSDL 2.0 w następujący sposób:
<?xml version="1.0" encoding="utf-8" ?>
<wsdl:description xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://www.w3.org/ns/wsdl"
xmlns:soap="http://www.w3.org/ns/wsdl/soap"
xmlns:calc="http://example.org/calculator"
xmlns:tns="http://example.org/calculatorService"
targetNamespace="http://example.org/calculatorService">
<!--
Abstract type definitions
-->
<wsdl:types>
<!--
<xs:schema>
<xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
</xs:schema>
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://example.org/calculator"
targetNamespace="http://example.org/calculator"
elementFormDefault="qualified"
attributeFormDefault="qualified">
<xs:element name="AddValuesRequest" type="tns:AddValuesType" />
<xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />
<xs:complexType name="AddValuesType">
<xs:sequence>
<xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
<xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="AddValuesResponseType">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Result" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:attribute name="Timestamp" type="xs:dateTime" />
<xs:element name="CalculationFault">
<xs:complexType>
<xs:sequence>
<xs:element name="ErrorCode" type="xs:int" />
<xs:element name="Reason" type="xs:string" />
</xs:sequence>
<xs:attribute ref="tns:Timestamp" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<!--
Abstract interface
-->
<wsdl:interface name="CalculatorInterface">
<wsdl:fault name="fault" element="calc:CalculationFault" />
<wsdl:operation name="AddValues" pattern="http://www.w3.org/ns/wsdl/in-out" style="http://www.w3.org/ns/wsdl/style/iri" wsdl:safe="true">
<wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
<wsdl:input messageLabel="in" element="calc:AddValuesRequest" />
<wsdl:output messageLabel="out" element="calc:AddValuesResponse" />
<wsdl:outfault messageLabel="fault" ref="tns:fault" />
</wsdl:operation>
</wsdl:interface>
<!--
Concrete binding definition
-->
<wsdl:binding name="CalculatorBinding" interface="tns:CalculatorInterface" type="http://www.w3.org/ns/wsdl/soap" soap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
<wsdl:operation ref="tns:AddValues" soap:mep="http://www.w3.org/2003/05/soap/mep/soap-response" />
<wsdl:fault ref="tns:fault" soap:code="soap:Sender" />
</wsdl:binding>
<!--
Concrete service definition
-->
<wsdl:service name="CalculatorService" interface="tns:CalculatorInterface">
<wsdl:endpoint name="CalculatorEndpoint" binding="tns:CalculatorBinding" address="http://localhost:8080/services/calculator" />
</wsdl:service>
</wsdl:description>
Różnice między WSDL 1.1 i 2.0
Graficzny przegląd różnic między obiema wersjami można zobaczyć na poniższym obrazku.
( Źródło )
Jak widać z obrazu, sekcja message
została usunięta, co jest teraz zawarte w sekcji interface
. Ponadto niektóre elementy zostały przemianowane, inne mają inną składnię, ale ogólnie obie wersje WSDL są w zasadzie takie same z wersją 2.0 wymagającą nieco mniejszego nakładu na pisanie w porównaniu do 1.1.
Oprócz mniejszego wpływu na definiowanie usług opartych na SOAP za pośrednictwem WSDL 2.0, nowsza wersja zapewnia również możliwości definiowania usług REST, chociaż WSDL 2.0, a nawet WADL NIE są zalecane dla usług RESTful, ponieważ są sprzeczne z samą ideą stojącą za tym.
Który styl wolisz
W sekcji powiązania WSDL opisano sposób powiązania usługi z protokołem przesyłania komunikatów SOAP. W powyższym przykładzie użyto document
jako stylu wiązania, który pozwala uporządkować treść SOAP tak, jak chcemy, o ile wynikowy wynik jest prawidłową instancją XML. Jest to domyślny styl wiązania i często nazywany Message-Oriented style
na Message-Oriented style
.
W przeciwieństwie do stylu document
żądania w stylu RPC
muszą zawierać zarówno nazwę operacji, jak i zestaw parametrów metody. Struktura instancji XML jest zatem wstępnie zdefiniowana i nie można jej zmienić.
Oprócz stylu wiązania sekcja wiązania definiuje również model tłumaczenia dla powiązań z komunikatami SOAP w nazwie literal
lub encoded
. Różnica między nimi polega na tym, że model literal
musi być zgodny ze zdefiniowaną przez użytkownika strukturą XSD, która może być używana do sprawdzania poprawności żądań i odpowiedzi, podczas gdy model encoded
musi używać typów danych XSD, takich jak xs:integer
lub xs:string
ale w zamian nie musi zatem być zgodny z żadnym schematem zdefiniowanym przez użytkownika. Utrudnia to jednak sprawdzenie poprawności treści wiadomości lub przekształcenie wiadomości za pomocą XSLT na inny format.
Połączenie stylu wiązania z modelem użytkowania pozwala na 4 różne wyniki wiadomości. Piąty wpis jest dodawany do listy, która jest często używana (choć tak naprawdę nie jest częścią standardu).
- RPC / zakodowane
- RPC / literał
- Dokument / zakodowany
- Dokument / literał
- Dokument / literał (opakowany)
W stylu przesyłania dokumentów / literałów istnieje wzorzec znany jako „zawinięty dokument / literał”. Jest to tylko wzorzec i nie jest częścią specyfikacji WSDL. Wzorzec ten ma wzmiankę w JSR 224 (JAX-WS: Java API dla usług sieciowych opartych na XML). ( Źródło )
Poniższa sekcja zawiera przegląd różnic dotyczących deklaracji WSDL lub schematu i ich wpływu na wynikowy format komunikatu SOAP na zmianę albo stylu wiązania, albo użycie definicji modelu.
RPC / zakodowane
WSDL:
...
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" type="xsd:int" />
<wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" type="xsd:int" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'RPC' and use to 'encoded' -->
...
Żądanie SOAP
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue xsi:type="xsd:int">1</FirstValue>
<SecondValue xsi:type="xsd:int">2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
Odpowiedź SOAP
<soap:envelope>
<soap:body>
<AddValuesResponse>
<Result xsi:type="xsd:int">3</Result>
</AddValuesResponse>
</soap:body>
</soap:envelope>
Plusy
- prosty WSDL
- Nazwa operacji i elementy dostępne w zapytaniu i odpowiedzi
Cons
- Jawna deklaracja typów XSI
- Trudne do zweryfikowania
- Niezgodny z WS-I
RPC / literał
WSDL:
...
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" type="xsd:int" />
<wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" type="xsd:int" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'RPC' and use to 'literal' -->
...
Żądanie SOAP
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue>1</FirstValue>
<SecondValue>2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
Odpowiedź SOAP
<soap:envelope>
<soap:body>
<AddValuesResult>
<Result>3</Result>
</AddValuesResult>
</soap:body>
</soap:envelope>
Plusy
- prosty WSDL
- Nazwa operacji i elementy dostępne w zapytaniu i odpowiedzi
- Nie jest wymagana specyfikacja typu XSI
- Zgodny z WS-I
Cons
- Trudne do zweryfikowania
Dokument / zakodowany
W związku z tym nie ma sensu pominięty.
Dokument / literał
WSDL:
...
<types>
<schema>
<element name="FirstValueElement" type="xsd:int" />
<element name="SecondValueElement" type="xsd:int" />
<element name="ResultValueElement" type="xsd:int" />
</schema>
</types>
<wsdl:message name="AddValues">
<wsdl:part name="FirstValue" element="FirstValueElement" />
<wsdl:part name="SecondValue" element="SecondValueElement" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="Result" element="ResultValueElement" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'Document' and use to 'literal' -->
...
Żądanie SOAP
<soap:envelope>
<soap:body>
<FirstValueElement>1</FirstValueElement>
<SecondValueElement>2</SecondValueElement>
</soap:body>
</soap:envelope>
Odpowiedź SOAP
<soap:envelope>
<soap:body>
<ResultElement>3</ResultElement>
</soap:body>
</soap:envelope>
Plusy
- Brak kodowania typu XSI
- W stanie zweryfikować ciało
- WS-I zgodny z ograniczeniami
Cons
- WSDL jest bardziej skomplikowany ze względu na dodatkową definicję XSD
- Nazwa operacji została utracona
- WS-I zezwala tylko na jedno dziecko w ciele SOAP
Dokument / literał (opakowany)
WSDL:
...
<types>
<schema>
<element name="AddValues">
<complexType>
<sequence>
<element name="FirstValue" type="xsd:int" />
<element name="SecondValue" type="xsd:int" />
</sequence>
</complexType>
</element>
<element name="AddValuesResponse">
<complexType>
<sequence>
<element name="ResultValue" type="xsd:int" />
</sequence>
</complexType>
</element>
</schema>
</types>
<wsdl:message name="AddValues">
<wsdl:part name="in" element="AddValues" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
<wsdl:part name="out" element="AddValuesResponse" />
</wsdl:message>
<wsdl:portType name="CalculatorEndpoint">
<wsdl:operation="AddValues">
<wsdl:input message="AddValues" />
<wsdl:output message="AddValuesResponse" />
</wsdl:operation>
</wsdl:portType>
<!-- binding style set to 'Document' and use to 'literal' -->
...
Żądanie SOAP
<soap:envelope>
<soap:body>
<AddValues>
<FirstValue>1</FirstValue>
<SecondValue>2</SecondValue>
</AddValues>
</soap:body>
</soap:envelope>
Odpowiedź SOAP
<soap:envelope>
<soap:body>
<AddValuesResponse>
<Result>3</Result>
</AddValuesResponse>
</soap:body>
</soap:envelope>
Plusy
- Brak kodowania typu XSI
- W stanie zweryfikować ciało
- Nazwa operacji i elementy dostępne w zapytaniu i odpowiedzi
- Zgodny z WS-I
Cons
- WSDL jest bardziej skomplikowany ze względu na dodatkową definicję XSD
UDDI
Universal Description, Discovery and Integration (UDDI)
to otwarta inicjatywa branżowa stworzona w 2000 roku, która działa jako oparty na XML rejestr żółtych stron dla usług internetowych, który pomaga znaleźć usługi rozwiązujące określone zadania. Aby znaleźć odpowiednią usługę, należy ją najpierw zarejestrować w rejestrze usług WWW, takim jak UDDI.
UDDI działa na wymianie komunikatów SOAP i zapewnia dostęp do dokumentów WSDL, których można użyć do wywołania faktycznej usługi internetowej.
UDDI zapewnia kryteria wyszukiwania takie jak
- identyfikator firmy
- Nazwa firmy
- Lokalizacja Biznesu
- Kategoria biznesu
- rodzaj usługi według nazwy
- adresy URL wykrywania
Jednak dużą wadą obecnego UDDI jest to, że pozwala on na użycie tylko jednego kryterium w instrukcji wyszukiwania. Dlatego niektórzy implementatorzy modulowali swoje implementacje UDDI, aby umożliwić zapytania spawnujące wiele UDDI jednocześnie, a następnie agregować zwrócone wyniki.
W praktyce jednak UDDI nie jest używane tak często. Niektórzy twierdzą nawet, że UDDI nie żyje, odkąd IBM, Microsoft i SAP zamknęły swoje usługi UDDI w 2005 roku .
Dalsze uwagi:
SOAP / WSDL zapewnia szeroki zakres wsparcia narzędziowego, a także pozwala dynamicznie generować kody pośredniczące zarówno dla klientów, jak i serwerów, ponieważ rodzaj komunikatów i wymienianych danych jest dobrze zdefiniowany za pomocą wbudowanych lub połączonych schematów XSD.
Podczas gdy WSDL 2.0 ma mniejszy narzut związany z definiowaniem usług sieciowych, niektóre języki wciąż nie przyjęły nowego standardu. Popularne narzędzia Java, takie jak wsimport
(z Oracle / Sun) lub wsdl2java
(z Apache CXF), nie są w stanie poprawnie obsługiwać opisów WSDL 2.0. Dlatego ze względu na kompatybilność nadal zaleca się stosowanie WSDL 1.1. Jeśli potrzebujesz rozwinąć usługę SOAP opartą na WSDL 2.0 w Javie, zajrzyj do wsdl2java
z projektu Apache Axis2 .
Bardziej popularne są jednak usługi API oparte na HTTP, które łączą wywołania operacji HTTP z czystymi zrozumiałymi dla ludzi identyfikatorami URI i pewnymi dostosowaniami protokołu, aby wykonać zadanie, usługi oparte na REST , które w pełni odpowiadają rzeczywistym zaleceniom, lub własne protokoły na poziomie bajtów, takie jak np. OFTP2 .
SOAP jest nadal użyteczny w dzisiejszych czasach, jeśli nie można mapować zadania bezpośrednio do zasobów, tak jak robią to usługi podstawowe HTTP / REST, ponieważ zadanie do wykonania reprezentuje naturalnie akcję lub musi zdefiniować określoną semantykę transakcji. Również jeśli nie masz zasobów do zdefiniowania lub wdrożenia własnego protokołu, prawdopodobnie lepiej jest użyć SOAP. SOAP jest szczególnie użyteczny, jeśli masz do czynienia z orkiestracją, ponieważ opis WSDL w połączeniu z UDDI pozwala dynamicznie łączyć usługi.
Usługa Java Client for Weather usługa sieciowa open source dostępna na http://www.webserviceX.NET
package com.test.ws.example;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
/*
* WSDL url : http://www.webservicex.com/globalweather.asmx?WSDL
* Endpoint URL: http://www.webservicex.com/globalweather.asmx */
public class WSClient {
public static void main(String args[]) {
try {
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Generate SOAP request XML
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
MimeHeaders header = soapMessage.getMimeHeaders();
header.setHeader("SOAPAction", "http://www.webserviceX.NET/GetCitiesByCountry");
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("web", "http://www.webserviceX.NET");
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement("GetCitiesByCountry", "web");
SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("CountryName", "web");
soapBodyElem1.addTextNode("INDIA");
soapMessage.saveChanges();
soapMessage.writeTo(System.out);
// Call webservice endpint
String url = "http://www.webservicex.com/globalweather.asmx";
SOAPMessage soapResponse = soapConnection.call(soapMessage, url);
Source sourceContent = soapResponse.getSOAPPart().getContent();
// Print SOAP response
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
System.out.println("Response SOAP Message \n");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
soapConnection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Tworzenie prostej usługi sieci Web i klientów za pomocą JAX-WS (dokument / literał)
To jest katalog projektu.
- Interfejs punktu końcowego usługi
Najpierw utworzymy interfejs punktu końcowego usługi. Adnotacja javax.jws.WebService @WebService
definiuje klasę jako punkt końcowy usługi sieci Web.
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
// Service Interface with customize targetNamespace
@WebService(targetNamespace = "http://hello-soap/ws")
@SOAPBinding(style = Style.DOCUMENT, use=Use.LITERAL) //optional
public interface HelloSoap {
@WebMethod String getHelloSoap(String name);
}
- Implementacja punktu końcowego usługi (SEI)
Następnie utworzymy implementację punktu końcowego usługi. Stworzymy jawny interfejs poprzez dodanie elementu endpointInterface
do adnotacji @WebService
w klasie implementacji. Oto zestaw reguł 28.1.1 Wymagania dotyczące punktu końcowego JAX-WS, których muszą przestrzegać punkty końcowe JAX-WS. Metoda getHelloSoap zwraca klientowi pozdrowienie z przekazaną mu nazwą.
import javax.jws.WebService;
// Customized Service Implementation (portName,serviceName,targetNamespace are optional)
@WebService(portName = "HelloSoapPort", serviceName = "HelloSoapService",
endpointInterface = "com.wonderland.hellosoap.HelloSoap", targetNamespace = "http://hello-soap/ws")
public class HelloSoapImpl implements HelloSoap {
@Override
public String getHelloSoap(String name) {
return "[JAX-WS] Hello : " + name;
}
}
- Wydawca punktu końcowego usługi sieci Web
import javax.xml.ws.Endpoint;
public class HelloSoapPublisher {
public static void main(String[] args) {
// creating web service endpoint publisher
Endpoint.publish("http://localhost:9000/ws/hello-soap", new HelloSoapImpl());
}
}
- W kolejnych krokach uruchomimy
HelloSoapPublisher.java
jako aplikację Java. Następnie przejrzymy plik WSDL, żądając adresu URLhttp://localhost:9000/ws/hello-soap?wsdl
w przeglądarce internetowej.
http: // localhost: 9000 / ws / hello-soap? wsdl
Jeśli format danych XML jest wyświetlany w przeglądarce internetowej, jesteśmy gotowi do przejścia do następnego kroku.
Uwaga:
Jeśli pojawi się komunikat o błędzie, być może trzeba użyć narzędziawsgen
do wygenerowania niezbędnych przenośnych artefaktów JAX-WS. Nie jesteśmy tutajwsgen
o narzędziuwsgen
.
- Klient usługi sieci Web
Ostatnim krokiem jest utworzenie klienta, który uzyskuje dostęp do naszej opublikowanej usługi.
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class HelloSoapClient {
public static void main(String[] args) throws Exception {
// create wsdl url
URL wsdlDocumentUrl = new URL("http://localhost:8000/ws/hello-soap?wsdl");
QName helloSoapService = new QName("http://hello-soap/ws", "HelloSoapService");
// create web service
Service service = Service.create(wsdlDocumentUrl, helloSoapService);
// get object of pointed service port
HelloSoap helloSoap = service.getPort(HelloSoap.class);
// testing request
System.out.println(helloSoap.getHelloSoap("Soap "));
}
}
Wyjście: [JAX-WS] Hello : Soap
Uwaga: Numer portu zmieniono na 8000
w naszym kliencie usług internetowych. Powodem jest to, że użyłem Eclipse IDE, TCP/IP monitor
narzędzia TCP/IP monitor
do śledzenia wiadomości (Więcej informacji: Jak śledzić komunikat SOAP w Eclipse IDE ). Do celów testów funkcjonalnych wypróbuj SoapUI | Testy funkcjonalne dla interfejsów API SOAP i REST .