Beheersen van SOAP API-testen. SOAP-protocol en webservices

10 antwoorden

WSDL is een XML-document dat een webservice beschrijft. Het staat eigenlijk voor Web Services Definition Language.

SOAP is een op XML gebaseerd protocol waarmee informatie tussen applicaties kan worden uitgewisseld via een specifiek protocol (zoals HTTP of SMTP). Het staat voor Simple Object Access Protocol en gebruikt XML als berichtenformaat om informatie over te brengen.

REST is een architectuurstijl voor netwerksystemen en staat voor de overdracht van een representatieve staat. Het is zelf geen standaard, maar maakt gebruik van standaarden zoals HTTP, URL, XML, etc.

Elke keer dat iemand SOAP/WSDL noemt, denk ik aan objecten en klassen die in xml zijn gedefinieerd...

"Je gebruikt SOAP net als elke andere PHP-klasse. In dit geval bestaat de klasse echter niet in de lokale versie bestandssysteem applicaties, maar op een externe host, toegankelijk via http."... "Als we overwegen een SOAP-service te gebruiken als een andere PHP-klasse, dan WSDL-document is een lijst van allemaal beschikbare methoden en klasse-eigenschappen."

En als iemand het over REST heeft, denk ik aan HTTP-opdrachten (request-methoden) zoals POST, GET en DELETE

Voorbeeld: in eenvoudige woorden, als u een rekenmachinewebservice heeft.

WSDL: WSDL heeft het over de functionaliteit die u kunt implementeren of aan de klant kunt tonen. Bijvoorbeeld: optellen, verwijderen, aftrekken, enz.

SOAP: Wanneer u SOAP gebruikt, voert u feitelijk acties uit zoals doDelete(), doSubtract(), doAdd(). SOAP en WSDL zijn dus appels en peren. We moeten ze niet vergelijken. Ze hebben allebei hun eigen functionaliteit.

Waarom we SOAP en WSDL gebruiken: Om onafhankelijke gegevens over het platform uit te wisselen.

EDIT: normaal Alledaagse leven:

WSDL: Als we naar een restaurant gaan, zien we menu-items, dit is WSDL.

Proxy-klassen: Nu we naar de menu-items hebben gekeken, stellen we onze gedachten samen (verwerken we onze visie in de bestelling): Dus in principe maken we Proxy-klassen gebaseerd op het WSDL-document.

ZEEP: Als we vervolgens eten bestellen op basis van het menu: wordt er gesuggereerd dat we proxyklassen gebruiken om servicemethoden aan te roepen die met SOAP worden gedaan:)

SOAP → SOAP (Simple Object Access Prototype) is een op protocollen gebaseerde applicatielaag ontworpen voor machine-to-machine-communicatie. Het protocol definieert standaardregels. Alle partijen die een bepaald protocol gebruiken, moeten zich aan de regels van het protocol houden. Net als TCP wordt het afgewikkeld op de transportlaag. Het SOAP-protocol zal worden begrepen op applicatieniveau (elke applicatie die SOAP ondersteunt - Axis2, .Net).

WSDL -> SOAP-bericht bestaat uit SoapEnevelope->SoapHeader en SoapBody. Het definieert niet wat het berichtformaat zal zijn? welke alle transporten (HTTP, JMS) worden ondersteund? zonder deze informatie. Voor elke klant die een specifieke webservice wil gebruiken, is het moeilijk om een ​​SOAP-bericht te maken. Zelfs als ze dat wel doen, weten ze niet zeker of het altijd zal werken. WSDL is een redder in nood. WSDL (Web Services Description Language) definieert de bewerkingen, berichtformaten en transportgegevens voor een SOAP-bericht.

REST → REST (Representation State Transfer) is gebaseerd op transport. In tegenstelling tot SOAP, dat actiegericht is, is REST meer hulpbronnengericht. REST vindt bronnen met behulp van een URL (bijvoorbeeld -http://(serverAddress)/employees/employeeNumber/12345) en is afhankelijk van het transportprotocol (met HTTP-GET, POST, PUT, DELETE,...) voor acties om bronnen uit te voeren . De REST-service vindt een bron op basis van de URL en voert een actie uit op basis van het transportactiewerkwoord. Het gaat meer om architecturale stijl en conventies.

SOAP staat voor Simple (sic) Object Access Protocol. Het was bedoeld om externe procedureaanroepen naar externe objecten te maken door XML via HTTP te verzenden.

WSDL is een beschrijvingstaal voor webservices. Een verzoek dat eindigt op een ".wsdl"-eindpunt zal ertoe leiden dat er een XML-bericht wordt gepresenteerd waarin het verzoek en het antwoord worden beschreven dat naar verwachting zal worden gebruikt. Het beschrijft het contract tussen de dienst en de klant.

REST gebruikt HTTP om berichten naar services te verzenden.

SOAP is een specificatie, REST is een stijl.

Je gaat niet ‘zomaar’ iets ingewikkelds begrijpen.

WSDL is een op XML gebaseerde taal voor het beschrijven van een webservice. Het beschrijft de berichten, bewerkingen en transportnetwerkinformatie die door de service worden gebruikt. Deze webservices maken doorgaans gebruik van SOAP, maar kunnen ook andere protocollen gebruiken.

WSDL is leesbaar door een programma en kan daarom worden gebruikt om (een deel van) de clientcode te genereren die nodig is om een ​​webservice aan te roepen. Dit is wat het betekent om SOAP-georiënteerde webservices ‘zelfbeschrijvend’ te noemen.

REST is helemaal niet gerelateerd aan WSDL.

Wikipedia zegt: "Web Services Description Language is een op XML gebaseerde taal die een model biedt voor het beschrijven van webservices." Met andere woorden: WSDL verwijst naar een webservice zoals Javadoc verwijst naar de Java-bibliotheek.

Het leuke van WSDL is echter dat software kan client en server genereren met behulp van WSDL.

Brett McLaughlin Vertaling door Ilya Chekmenev

SOAP is een Simple Object Access Protocol Toegangsprotocol). Als je er nog nooit van hebt gehoord, dan moet je in de middle of nowhere wonen, ver van de bewoonde wereld. Het is de laatste mode geworden op het gebied van webprogrammering en een integraal onderdeel webservices, die met zoveel fanatisme worden gebruikt webontwikkeling laatste generatie. Als je hebt gehoord van de .NET- of peer-to-peer-revolutie van Microsoft, dan heb je gehoord van technologieën die afhankelijk zijn van SOAP (zelfs als je niet weet wat het is). Er is er niet één, maar twee SOAP-implementaties van Apache en Microsoft, waaraan duizenden pagina's zijn gewijd op hun MSDN-ondersteuningssite (http://msdn.microsoft.com/).

In dit artikel zal ik je vertellen wat SOAP is en waarom het zo'n belangrijk onderdeel is in de ontwikkeling van het webprogrammeerparadigma. Dit zal u helpen de basisprincipes over te slaan en direct aan de slag te gaan met de SOAP-toolkit. Daarna geef ik een kort overzicht van bestaande SOAP-projecten en duik ik in de implementatie van Apache. Dit artikel is niet bedoeld om een ​​compleet beeld te geven van SOAP; het boek Java & XML, 2e editie, vult veel van de hiaten op. Op veel van de vragen die na het lezen van dit artikel opkwamen, vindt u in het boek antwoorden.

Invoering

Eerst moet je begrijpen wat SOAP is. U kunt de volledige (en vrij lange) W3C-opinie lezen op http://www.w3.org/TR/SOAP. Als je het eenmaal hebt uitgezocht en alle schil hebt weggegooid, zul je begrijpen dat SOAP slechts een protocol is. Het is een eenvoudig protocol (u hoeft geen nieuw protocol te schrijven om het te gebruiken) gebaseerd op het idee dat er op een bepaald punt in een gedistribueerde architectuur behoefte is aan informatie-uitwisseling. Voor systemen waarin de mogelijkheid bestaat van overbelasting en moeilijkheden bij verwerkingsprocessen, is dit protocol bovendien zeer voordelig omdat het licht van gewicht is en een minimale hoeveelheid bronnen vereist. Ten slotte kunnen alle bewerkingen via HTTP worden uitgevoerd, wat het mogelijk maakt om lastige zaken als firewalls te omzeilen en uzelf te beschermen tegen luisteren via sockets op een ongelooflijk aantal poorten. Het belangrijkste is dat je dit beseft, en al het andere zijn details.

Natuurlijk wilt u deze details graag weten, en ik zal ze niet negeren. De SOAP-specificatie bestaat uit drie basiscomponenten: een SOAP-envelop, een reeks versleutelingsregels en een middel voor interactie tussen het verzoek en het antwoord. Laten we een SOAP-bericht beschouwen als een gewone brief. Herinner je je nog die oude dingen in enveloppen met een postzegel en het adres op de voorkant geschreven? Deze analogie zal u helpen het concept van SOAP als een 'envelop' duidelijker te begrijpen. Figuur 12.1 toont SOAP-processen in de vorm van deze analogie.

Figuur 12-1. SOAP-berichtproces

Houd dit beeld in gedachten en laten we eens kijken naar de drie componenten van de SOAP-specificatie. Ik zal kort over elk van hen praten en voorbeelden geven die het concept het beste weergeven. Deze drie belangrijke componenten maken SOAP zo belangrijk en betekenisvol. Foutafhandeling, ondersteuning voor verschillende coderingen, parameterserialisatie en het feit dat SOAP in de meeste gevallen via HTTP werkt, maken het aantrekkelijker dan andere oplossingen voor gedistribueerde protocollen. SOAP biedt hoge graad interacties met andere toepassingen, die ik in mijn boek gedetailleerder heb behandeld. Voor nu wil ik me concentreren op de kernelementen van SOAP.

Envelop

Een SOAP-envelop is vergelijkbaar met een gewone brievenenvelop. Het bevat informatie over het bericht dat wordt gecodeerd in het hoofdgedeelte van SOAP, inclusief informatie over de ontvanger en afzender, evenals informatie over het bericht zelf. De header van de SOAP-envelop kan bijvoorbeeld aangeven hoe het bericht moet worden verwerkt. Voordat een toepassing een bericht begint te verwerken, onderzoekt het de informatie over het bericht, inclusief of het bericht überhaupt kan worden verwerkt. In tegenstelling tot de situatie bij standaard XML-RPC-aanroepen (weet je nog? XML-RPC-berichten, encryptie, etc., alles wordt gecombineerd in een enkel XML-fragment), vindt bij SOAP de voortdurende verwerking plaats om iets over het bericht te leren. Een typisch SOAP-bericht kan ook een coderingsstijl bevatten die de ontvanger helpt bij het verwerken van het bericht. Voorbeeld 12-1 toont een SOAP-envelop die eindigt met een coderingsspecificatie.

Voorbeeld 12-1: SOAP-envelop

Zeepkist http://www-106.ibm.com/developerworks/library/x-soapbx1.html

Zoals u kunt zien, wordt de codering in de envelop geplaatst, waardoor de toepassing kan bepalen (met behulp van de attribuutwaarde coderingStijl), of het binnenkomende bericht in het element kan lezen Lichaam. Zorg ervoor dat de naamruimte van de SOAP-envelop correct is, anders zullen de SOAP-servers die uw bericht ontvangen een fout melden die niet overeenkomt met de versie en kunt u niet met hen communiceren.

Encryptie

Het tweede belangrijke element van SOAP is de mogelijkheid om aangepaste gegevenstypen te coderen. Met RPC (en XML-RPC) kan encryptie alleen worden uitgevoerd op vooraf gedefinieerde gegevenstypen die worden ondersteund in de XML-RPC-toolkit die u hebt gedownload. Voor het coderen van andere soorten gegevens moet u de RPC-server en -client zelf aanpassen. Met SOAP kan een XML-schema vrij eenvoudig worden gebruikt om nieuwe gegevenstypen te specificeren (met behulp van de structuur complexType, besproken in hoofdstuk 2 van mijn boek), en deze nieuwe typen kunnen in XML worden weergegeven als onderdeel van het hoofdgedeelte van SOAP. Dankzij XML Schema-integratie kunt u elk type gegevens in een SOAP-bericht versleutelen door deze logisch te beschrijven in een XML-schema.

Telefoongesprek

De beste manier om te begrijpen hoe een SOAP-oproep werkt, is door deze te vergelijken met iets waarmee u bekend bent, zoals XML-RPC. Zoals u zich herinnert, lijkt de XML-RPC-aanroep op het codefragment uit voorbeeld 12-2.

Voorbeeld 12-2. Aanroep naar XML-RPC

// Specificeren van de XML-processor (parser) om XmlRpc.setDriver("org.apache.xerces.parsers.SAXParser"); // Specificatie van de server waarmee verbinding wordt gemaakt XmlRpcClient client = new XmlRpcClient("http://rpc.middleearth.com"); // Parameters maken Vector params = new Vector(); params.addElement(vluchtnummer); params.addElement(numSeats); params.addElement(creditCardType); params.addElement(creditCardNum); // Request Boolean buyTickets = (Boolean)client.execute("ticketCounter.buyTickets", params); // Verwerk het antwoord

Ik heb een eenvoudig programma gemaakt voor het bestellen van vliegtickets. Kijk nu eens naar voorbeeld 12.3, waarin een SOAP-oproep wordt gedemonstreerd.

Voorbeeld 12-3. Bel naar SOAP

// Parameters maken Vector params = new Vector(); params.addElement(new Parameter("flightNumber", Integer.class, flightNumber, null)); params.addElement(new Parameter("numSeats", Integer.class, numSeats, null)); params.addElement(new Parameter("creditCardType", String.class, creditCardType, null)); params.addElement(new Parameter("creditCardNumber", Long.class, creditCardNum, null)); // Maak een Call-object Bel bel= nieuwe oproep(); call.setTargetObjectURI("urn:xmltoday-vliegtickets"); call.setMethodName("buyTickets"); call.setEncodingStyleURI (Constanten.NS_URI_SOAP_ENC); call.setParams(params); // Oproepantwoord res = call.invoke(nieuwe URL("http://rpc.middleearth.com"), ""); // Verwerk het antwoord

Zoals u kunt zien, wordt de daadwerkelijke oproep weergegeven door het object Telefoongesprek, geheugenbewoner. Hiermee kunt u het oproepdoel, de oproepmethode, de coderingsstijl, parameters en vele andere parameters specificeren die niet in dit voorbeeld worden weergegeven. Dit is een flexibeler mechanisme dan de XML-RPC-methode, waardoor u expliciet een set kunt specificeren verschillende parameters, die indirect zijn gedefinieerd in XML-RPC. Verderop in dit artikel leert u meer over het oproepproces, inclusief hoe SOAP ongeldige verzoeken afhandelt, de foutenhiërarchie en natuurlijk de geretourneerde oproepresultaten.

Na dit korte introductie je weet al genoeg om geïnteresseerd te zijn in dit grappige ding. Laat me u nu kennis laten maken met de SOAP-implementatie die ik ga gebruiken. Ik zal de redenen uitleggen waarom ik ervoor heb gekozen en enkele codevoorbeelden bekijken.

Instellingen

Nu je de basis van het concept hebt geleerd, is het tijd voor het leuke gedeelte: programmeren. Hiervoor heeft u een handig project of product nodig, dat gemakkelijker te vinden is dan het op het eerste gezicht lijkt. Als u een Java-project nodig heeft dat SOAP-mogelijkheden biedt, hoeft u niet lang te zoeken om er een te vinden. Er zijn twee groepen producten: commercieel en gratis. Net als in mijn boek zal ik het vermelden van commerciële producten vermijden. Dit is helemaal niet omdat ze slecht zijn (integendeel, sommige zijn uitstekend), maar omdat ik zou willen dat elke lezer een van de gegeven voorbeelden zou kunnen proberen. Dit komt door de beschikbaarheid die velen hebben commerciële producten niet bezitten. U moet betalen om ze te gebruiken, of ze tijdelijk gebruiken gedurende een beperkte periode na het downloaden.

Zo hebben we projecten vlot benaderd open source(open source). Vanuit dit gebied kan ik maar één product noemen: Apache SOAP. Het bevindt zich op http://xml.apache.org/soap en biedt een SOAP-toolkit voor Java. Op het moment van schrijven is versie 2.2 uitgebracht, die u kunt downloaden van de Apache-website. Het is deze versie die ik zal gebruiken in de voorbeelden voor dit artikel.

Andere alternatieven

Voordat ik verder ga met het installeren en configureren van Apache SOAP, zal ik een paar vragen beantwoorden die mogelijk bij u zijn opgekomen. Ik denk dat ik heel duidelijk heb uitgelegd waarom ik geen commerciële producten gebruik. Misschien denk je echter aan een aantal andere open source- of gerelateerde projecten die je misschien graag zou willen gebruiken, en het verbaast je dat ik daar geen commentaar op heb gegeven.

Hoe zit het met IBM SOAP4J?

Als eerste op de lijst met alternatieven staat een implementatie van IBM: SOAP4J. Het werk van IBM vormde de basis van het Apache SOAP-project, net toen IBM's XML4J uitgroeide tot wat nu bekend staat als het XML-parser Apache Xerces. Aangenomen wordt dat de IBM-implementatie opnieuw zal worden ontworpen en zal worden samengevoegd met Apache SOAP. Ongeveer hetzelfde gebeurde met IBM's XML4J: nu biedt het alleen verpakkingen in Xerces. Dit benadrukt alleen de trends. grote fabrikanten ondersteunen en gebruiken vaak OpenSource-projecten, in in dit geval beide projecten (Apache en IBM) gebruiken dezelfde codebase.

Is Microsoft uit het spel?

Natuurlijk niet. Microsoft en zijn SOAP-implementatie, evenals de hele .NET-beweging (in meer detail besproken in mijn boek), zijn behoorlijk belangrijk. Ik wilde echt het grootste deel van mijn tijd besteden aan het gedetailleerd bekijken van de SOAP-implementatie van Microsoft, maar deze ondersteunt alleen COM-objecten en geen Java. Om deze redenen kon een dergelijke beschrijving niet worden opgenomen in een artikel over Java en XML. Microsoft heeft echter (ondanks alle klachten die wij als ontwikkelaars over dit bedrijf hebben) belangrijk werk verricht op het gebied van webservices, en je zult een fout maken als je het afwijst zonder na te denken, alleen geleid door rauwe emoties. Als u met COM- of Visual Basic-componenten moet werken, raad ik u ten zeerste aan de Microsoft SOAP-toolkit te gebruiken, beschikbaar op http://msdn.microsoft.com/library/default.asp?url=/nhp/Default .asp ?contentid=28000523 samen met vele andere SOAP-bronnen.

Wat is Axis?

Degenen onder jullie die Apache-activiteiten volgen, hebben vast wel eens gehoord van Apache Axis. Axis is een SOAP-toolkit van de volgende generatie, ook ontwikkeld onder de Apache XML-paraplu. SOAP (een specificatie, geen specifieke implementatie), die zich de laatste tijd snel en radicaal heeft ontwikkeld, is erg moeilijk te volgen. Het is ook een behoorlijke uitdaging om een ​​versie van SOAP te maken die volledig voldoet aan de huidige eisen terwijl deze evolueren. Als gevolg hiervan biedt de huidige versie van Apache SOAP een oplossing die beperkt is door het ontwerp. Nadat ze hadden besloten dat het niet de moeite waard was om de bestaande tool volledig opnieuw te ontwerpen, begonnen de Apache-ontwikkelaars een project te maken op basis van de nieuwe code. Zo werd Axis geboren. Ook de naam van SOAP veranderde, eerst van SOAP naar XP en vervolgens naar XMLP. Vervolgens werd de specificatienaam verwijderd uit de naam van de nieuwe SOAP en werd de naam "Axis" geboren. Maar nu lijkt het erop dat het W3C teruggaat naar de naam van de SOAP-specificatie (versie 1.2 of 2.0), dus er kunnen nog dingen veranderen en er zal zelfs nog meer verwarring ontstaan!

Beschouw IBM SOAP4J als een architectuur1 van de SOAP-toolkit. Hoe zit het met Apache SOAP (besproken in dit artikel) als architectuur?2. En Axis vertegenwoordigt de ?3-architectuur, een architectuur van de nieuwe generatie. Dit project maakt gebruik van SAX terwijl Apache SOAP op DOM is gebaseerd. Bovendien biedt Axis, in tegenstelling tot Apache SOAP, een gebruiksvriendelijkere benadering van gebruikersinteractie. Nadat je deze voordelen hebt opgesomd, vraag je je misschien af ​​waarom ik Axis niet als mijn studievak heb gekozen. Het zou gewoon een beetje voorbarig zijn. Momenteel wordt alleen versie 0.51 van Axis voorbereid voor release. Dit is nog geen bètaversie, of zelfs een alfaversie. Ik zou graag over de nieuwe Axis-functies willen praten, maar u heeft geen enkele kans om uw management ervan te overtuigen dat u sub-alfa open source-software kunt gebruiken voor uw kritieke systeembehoeften. Dus besloot ik me te concentreren op iets dat echt is je kunt gebruiken al Vandaag- Apache-SOAP. Ik denk dat tegen de tijd dat de definitieve versie van Apache Axis uitkomt, ik dit materiaal in de volgende editie van mijn boek zal bijwerken. Laten we ons tot die tijd concentreren op de oplossing die al beschikbaar is.

Installatie

Er zijn twee mogelijke vormen van SOAP-installatie. De eerste is het starten van een SOAP-client die de SOAP API gebruikt om te communiceren met een server die SOAP-berichten kan accepteren. De tweede manier is om een ​​SOAP-server te gebruiken waar berichten van kunnen worden ontvangen SOAP-client. In deze sectie heb ik beide procedures beschreven.

Cliënt

Om de SOAP-client te gebruiken, moet u eerst Apache SOAP downloaden, beschikbaar op http://xml.apache.org/dist/soap. Ik heb versie 2.2 gedownload in binair formaat (uit de submap versie-2.2). Vervolgens moet u de inhoud van het archief uitpakken in een map op uw computer. In mijn geval was het de directory javaxml2 (c:\javaxml2 op mijn Windows-computer /javaxml2 op mijn Mac OS X-computer). Als gevolg hiervan werden de bestanden uitgepakt in /javaxml2/soap-2_2. U moet ook het JavaMail-pakket downloaden dat verkrijgbaar is bij Sun http://java.sun.com/products/javamail/. Het is vereist om het SMTP-overdrachtsprotocol te ondersteunen dat door Apache SOAP wordt gebruikt. Download dan het Java Beans Activation Framework (JAF), ook verkrijgbaar bij Sun http://java.sun.com/products/beans/glasgow/jaf.html. Gebaseerd op de veronderstelling dat Xerces of een andere XML-parser al geïnstalleerd en klaar voor gebruik is.

Opmerking: Zorg ervoor dat uw XML-parser JAXP-compatibel is en de naamruimte correct gebruikt. Uw parser voldoet waarschijnlijk aan deze vereisten. Als u problemen ondervindt, kunt u het beste terugkeren naar het gebruik van Xerces.

Opmerking: Gebruik nieuwste versies Xerces. Versie 1.4 en hoger zijn voldoende. Er zijn een aantal bugs in SOAP en Xerces 1.3(.1), dus ik raad het gebruik van deze combinatie af.

Pak de JavaMail- en JAF-pakketten uit en schakel ze vervolgens in jar-bestand s naar uw klassenpad en naar de bibliotheek zeep.pot. Elk van deze jar-bestanden moet zich in hoofdmap overeenkomstige programma, of in een submap /lib. Wanneer u klaar bent met uw variabele klassenpad zou er ongeveer zo uit moeten zien:

$ echo $CLASSPATH /javaxml2/soap-2_2/lib/soap.jar:/javaxml2/lib/xerces.jar: /javaxml2/javamail-1.2/mail.jar:/javaxml2/jaf-1.0.1/activation.jar

Voor Windows ziet het er als volgt uit:

c:\>echo %CLASSPATH% c:\javaxml2\soap-2_2\lib\soap.jar;c:\javaxml2\lib\xerces.jar; c:\javaxml2\javamail-1.2\mail.jar;c:\javaxml2\jaf-1.0.1\activation.jar

En voeg ten slotte de map toe javaxml2/soap-2_2/ in uw klassenpad om SOAP-voorbeelden uit te voeren. In dit hoofdstuk heb ik de opstelling voor verschillende voorbeelden beschreven.

Server

Om een ​​SOAP-compatibele set servercomponenten te maken, hebt u eerst een servlet-engine nodig. Net als in voorgaande hoofdstukken heb ik voor dit hoofdstuk als voorbeeld gebruikt Apache Tomcat(beschikbaar op http://jakarta.apache.org/). Je moet alles toevoegen wat de klant nodig heeft klassenpad server. De eenvoudigste manier om dit te doen is door te resetten zeep.pot, activatie.jar En mail.jar, evenals uw parser, in de bibliotheekmap van uw servlet-engine. Voor Tomcat is dit de map /lib, die bibliotheken bevat voor automatisch downloaden. Als u ondersteuning wilt bieden voor scripts (die niet in dit hoofdstuk worden besproken, maar wel in de Apache SOAP-voorbeelden staan), moet u bsf.jar(beschikbaar op http://oss.software.ibm.com/developerworks/projects/bsf) en js.jar(beschikbaar op http://www.mozilla.org/rhino/) naar dezelfde map.

Opmerking: Als je Xerces met Tomcat gebruikt, moet je de truc herhalen die ik in hoofdstuk 10 heb besproken. parser.jar V z_parser.jar, A jaxp.jar V z_jaxp.jar om ervoor te zorgen dat xerces.jar en de meegeleverde versie van JAXP wordt geladen vóór enige andere parser of JAXP-implementatie.

Start vervolgens uw servlet-engine opnieuw op, waarna u klaar bent om SOAP-servercomponenten te schrijven.

Routerservlet en beheerdersclient

Naast de basisbewerkingen bevat Apache SOAP zowel een routerservlet als een admin-client. Zelfs als u niet van plan bent ze te gebruiken, raad ik u aan ze te installeren om te testen of SOAP correct is geïnstalleerd. Dit proces is afhankelijk van welke servlet-engine u gebruikt, dus ik zal het installatieproces beperken tot Tomcat. Installatie-instructies voor enkele andere servlet-engines kunt u vinden op http://xml.apache.org/soap/docs/index.html.

Installatie onder Tomcat is heel eenvoudig: neem gewoon het bestand zeep.oorlog uit map soap-2_2/webapps en plaats het in de map $TOMCAT_HOME/webapps- en dat is het! Om de installatie te controleren, voert u het adres in uw browser in http://localhost:8080/soap/servlet/rpcrouter. U zou een antwoord moeten ontvangen dat vergelijkbaar is met het antwoord dat wordt weergegeven in figuur 12.2.

Figuur 12-2. Router RPC-servlet

Hoewel het bericht een foutmelding lijkt, geeft dit aan dat alles correct werkt. U zou hetzelfde antwoord moeten krijgen als u uw browser naar het klantadres van de beheerder verwijst: http://localhost:8080/soap/servlet/messagerouter.

Zorg ervoor dat u alle instructies volledig hebt gevolgd om het testen van de server en client te voltooien. Voer vervolgens de volgende Java-klasse uit, zoals hieronder weergegeven, om uw servlet-URL voor de RPC-routerservlet te ondersteunen:

C:\>java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter lijst Geïmplementeerde services:

Je zou moeten krijgen lege lijst diensten, zoals hierboven weergegeven. Als u berichten ontvangt, bekijk dan de lange lijst met mogelijke fouten die beschikbaar is op http://xml.apache.org/soap/docs/trouble/index.html. Dit is de meest uitgebreide lijst met problemen die u kunt tegenkomen. Als u een lege lijst ontvangt, betekent dit dat de installatie voltooid is en dat u klaar bent om de voorbeelden in dit hoofdstuk te gaan bekijken.

Laten we beginnen

Er zijn drie hoofdfasen bij het schrijven van op SOAP gebaseerde systemen. Nadat ik ze heb opgesomd, zal ik ze kort bespreken:

  • Kiezen tussen SOAP-RPC en SOAP-berichten;
  • Schrijven of toegang verkrijgen tot een SOAP-dienst;
  • Schrijven of toegang krijgen tot een SOAP-client.

De eerste stap is om te kiezen of u SOAP gaat gebruiken voor RPC-oproepen (waarbij een procedure op afstand op de server wordt uitgevoerd) of voor berichten (waarbij de client eenvoudigweg stukjes informatie naar de server verzendt). Hieronder bespreek ik deze processen in detail. Zodra u deze beslissing heeft genomen, moet u uw eigen service openen of creëren. Omdat we allemaal Java-professionals zijn, behandelt dit hoofdstuk uiteraard hoe u uw eigen Java-professional kunt maken. En tot slot moet u een klant voor deze service schrijven, dat is alles!

RPC of berichten?

Je eerste taak heeft niets met programmeren te maken en is meer van ontwerpkarakter. U moet kiezen of u de RPC- of berichtenservice wilt gebruiken. We gaan ervan uit dat je bekend bent met RPC (bijvoorbeeld door een van de hoofdstukken uit mijn boek te lezen). De client voert een procedure op afstand uit op de server en ontvangt vervolgens een antwoord. In dit scenario fungeert SOAP als een verbeterd XML-RPC-systeem dat een betere foutafhandeling en overdracht van complexe gegevenstypen via het netwerk mogelijk maakt. U bent al bekend met dit concept, en aangezien RPC-systemen gemakkelijker in SOAP te schrijven zijn, zal ik ermee beginnen. In dit artikel wordt beschreven hoe u een RPC-service en een RPC-client maakt en het systeem in werking stelt.

Een andere manier van werken met SOAP is gebaseerd op berichtenuitwisseling. In plaats van procedures op afstand uit te voeren, wordt het alleen gebruikt voor het uitwisselen van informatie. Zoals u kunt raden, is dit een krachtig hulpmiddel waarbij de client niet de individuele methoden van welke server dan ook hoeft te kennen. Het maakt het modelleren van systemen op afstand ook meer geïsoleerd doordat datapakketten (pakketten in figuurlijke zin, niet in netwerkzin) naar andere systemen kunnen worden verzonden. Tegelijkertijd hoeven andere systemen niets te weten over de bewerkingen die met deze gegevens zijn uitgevoerd. Deze stijl is complexer dan RPC-programmeren, dus ik zal deze hier niet beschrijven. Je vindt het in mijn boek, samen met andere details over business-to-business-interactie. Maak eerst kennis met SOAP-RPC-programmeren.

Zoals bij de meeste ontwerpproblemen is het nemen van deze beslissing uw verantwoordelijkheid. Analyseer uw applicatie en probeer te bepalen waarom u SOAP moet gebruiken. Als u een server en een reeks clients heeft die op aanvraag specifieke bedrijfsfuncties uitvoeren, dan is RPC meer geschikt voor u. IN ingewikkelde systemen, waarin gegevensuitwisseling meer inhoudt dan alleen het op verzoek uitvoeren van specifieke bedrijfsfuncties, verdient het gebruik van SOAP-berichten veel de voorkeur.

RPC-service

Nu de formaliteiten voorbij zijn, is het tijd om actie te ondernemen. Zoals je weet, heb je in RPC klassen nodig waarvan de methoden op afstand worden uitgevoerd.

Codefragmenten

Ik zal beginnen met het bekijken van enkele codefragmenten voor de server. Deze fragmenten zijn klassen met methoden die worden uitgevoerd voor RPC-clients. Ik heb code uit mijn boek als voorbeeld gebruikt. In plaats van eenvoudige klassen te gebruiken, heb ik een complexer voorbeeld gekozen om de mogelijkheden van SOAP zo duidelijk mogelijk te demonstreren. Dus ik gebruikte de CD-klasse als voorbeeld. Eerst definiëren we het element kaart voor elk niet-standaard parametertype. Voor attribuut coderingStijl, tenminste in Apache SOAP 2.2. u moet de waarde http://schemas.xmlsoap.org/soap/encoding/ opgeven. Dit is momenteel de enige ondersteunde codering. U moet de naamruimte voor het door de gebruiker gedefinieerde type opgeven en vervolgens de klassenaam, voorafgegaan door de naamruimte voor dat type. In ons geval heb ik voor deze doeleinden een fictieve naamruimte en een eenvoudig voorvoegsel " X". Gebruik vervolgens het attribuut javaType, vroeg echte naam Java-klasse (in dit geval - javaxml2.CD). En tot slot Kuralesil met attributen java2XMLClassName En xml2JavaClassName. Met hun hulp wordt een klasse gespecificeerd die wordt geconverteerd van Java naar XML en omgekeerd. Ik gebruikte de ongelooflijk handige BeanSerializer-klasse, ook inbegrepen bij Apache SOAP. Als uw aangepaste parameter de JavaBean-indeling heeft, voorkomt deze serializer en deserializer dat u uw eigen parameter hoeft te schrijven. Je hebt een klasse nodig met een standaardconstructor (onthoud dat ik voor de CD-klasse een eenvoudige, parameterloze constructor heb gedefinieerd) en publiceer alle gegevens van deze klasse met behulp van methoden setXXX En krijgXXX. Omdat klasse CD voldoet perfect aan al deze eisen, BeanSerializer werkt perfect.

Opmerking: Welke klas CD Voldoet aan de eisen BeanSerializer. maakt niet zoveel uit. De meeste klassen kunnen eenvoudig naar dit formaat worden geconverteerd. Daarom raad ik u aan om niet uw eigen serializers en deserializers te schrijven. Dit is een extra hoofdpijn (niets ingewikkelds, maar te nauwgezet) en ik raad u aan om uw energie te sparen en bonenconversie te gebruiken in uw aangepaste parameters. In veel gevallen vereisen bonenconversies alleen een standaardconstructor (geen parameters) in uw klasse.

Laten we nu opnieuw creëren kan bestand en installeer onze service opnieuw:

(gandalf)/javaxml2/Ch12$ java org.apache.soap.server.ServiceManagerClient http://localhost:8080/soap/servlet/rpcrouter xml/CDCatalogDD.xml

Aandacht: Als u uw servlet-engine laat draaien en tegelijkertijd een service opnieuw host, moet u de servlet-engine opnieuw opstarten om de nieuwe klassen voor de SOAP-service in te schakelen en de service opnieuw te hosten.

Nu hoeft u alleen nog maar de client aan te passen om nieuwe klassen en methoden te gebruiken. Voorbeeld 12-10 bevat aangepaste versie cliënt klasse CDAdder. Wijzigingen ten opzichte van de vorige versie zijn gemarkeerd.

Voorbeeld 12-10: Bijgewerkte klasse CDAdder

pakket javaxml2; java.net.URL importeren; java.util.Vector importeren; importeer org.apache.soap.Constanten; importeer org.apache.soap.Fault; importeer org.apache.soap.SOAPException; importeer org.apache.soap.encoding.SOAPMappingRegistry; importeer org.apache.soap.encoding.soapenc.BeanSerializer; importeer org.apache.soap.rpc.Call; importeer org.apache.soap.rpc.Parameter; importeer org.apache.soap.rpc.Response; importeer org.apache.soap.util.xml.QName; openbare klasse CDAdder( public void add(URL-URL, String-titel, String-artiest, String-label) genereert SOAPException ( System.out.println("Een CD toevoegen met de titel "" + titel + "" artiest "" + artiest + "" studio " + label); CD cd = nieuwe CD(titel, artiest, label); // Maak een call-object Call Call call = new Call(); call.setSOAPMappingRegistry (register); call.setTargetObjectURI("urn:cd-catalog"); call.setMethodName("addCD"); call.setEncodingStyleURI (Constanten.NS_URI_SOAP_ENC); // Parameters instellen Vectorparameters = new Vector(); params.addElement(nieuwe parameter("cd", CD.class, cd, null)); call.setParams(params); // Het Invoke call Response-antwoord verwerken; antwoord = oproep.aanroepen(url, ""); if (!response.generatedFault()) ( System.out.println("Het toevoegen van CD is met succes voltooid."); ) else ( Foutfout = response.getFault(); System.out.println(Fout: " + fout.getFaultString ()); public static void main(String args) ( if (args.length != 4) ( System.out.println("Sjabloon: java javaxml2.CDAdder " + "\"[CD-titel]\" \"[Naam artiest]\ " \"[Studio-CD]\""); return; try ( // URL van de SOAP-server waarmee verbinding wordt gemaakt URL url = new URL(args); // Waarden ophalen voor nieuwe CD String title = args; Strijkkunstenaar = args; Tekenreekslabel = args; // Voeg de CD CDAdder-adder toe = new CDAdder(); adder.add(url, titel, artiest, label); ) catch (Uitzondering e) ( e.printStackTrace(); ) ) )

De enige echt interessante verandering is het in kaart brengen van klassen CD:

// Wijs dit type toe zodat het kan worden gebruikt met SOAP SOAPMappingRegistry register = new SOAPMappingRegistry(); BeanSerializer-serializer = nieuwe BeanSerializer(); register.mapTypes(Constants.NS_URI_SOAP_ENC, nieuwe QName("urn:cd-catalog-demo", "cd"), CD.class, serializer, serializer);

Op deze manier kan een gebruikersparameter worden gecodeerd en via het netwerk worden verzonden. Ik heb je al verteld hoe de klas BeanSerializer kan worden gebruikt om parameters in JavaBean-indeling te verwerken, zoals class CD. Ik heb een plaatsingsdescriptor gebruikt om deze aan de server aan te geven, hoewel ik nu de client moet vertellen deze serializer en deserializer te gebruiken. Deze functie wordt uitgevoerd door de klas SOAPMappingRegister. Methode mapTypes() neemt de gecodeerde string (nogmaals, het is beter om hiervoor een constante te gebruiken NS_URI_SOAP_ENC), en informatie over het parametertype waarvoor speciale serialisatie moet worden gebruikt. De QName wordt eerst opgegeven. Dit is de reden waarom de vreemde naamruimte werd gebruikt in de hostingdescriptor. U moet hier dezelfde URN opgeven, evenals de lokale naam van het element (in dit voorbeeld "CD"), en vervolgens het Java-object Klas klasse die wordt geserialiseerd ( CD.klasse) en ten slotte een exemplaar van de klasse voor serialisatie en deserialisatie. Voor dit voorbeeld is in beide gevallen sprake van een instance BeanSerializer. Zodra al deze instellingen in het register zijn ingevoerd, stelt u het object op de hoogte Telefoongesprek met behulp van de methode setSOAPMapping-Register().

Je kunt deze klasse uitvoeren zoals eerder getoond, door een CD toe te voegen, en alles zou moeten werken zoals verwacht:

C:\javaxml2\build>java javaxml2.CDAdder http://localhost:8080/soap/servlet/rpcrouter "Tony Rice" "Manzanita" "Sugar Hill" Een cd toevoegen met de titel "Tony Rice" van Sugar Hill's "Manzanita" Een cd toevoegen is gelukt.

Ik heb de klassewijziging verlaten CDLister voor jou. Alles wordt volgens hetzelfde template geproduceerd. Om uzelf te testen, kunt u de voorbeeldbestanden voor mijn boek raadplegen, die deze bijgewerkte klassen al bevatten.

Opmerking: u kunt dit beslissen omdat de klasse CDLister heeft geen directe interactie met het object CD(teruggegeven via methode lijst() het type is belangrijk Hashtabel), dan hoeft u geen wijzigingen aan te brengen. Echter, de teruggekeerde klasse Hashtabel bevat objectinstanties CD. Als SOAP niet weet hoe ze moeten worden gedeserialiseerd, genereert de client een foutmelding. In dit geval moet u het probleem in het object opgeven om het probleem op te lossen Telefoongesprek kopiëren SOAPMappingRegister.

Efficiënte foutafhandeling

Nu je aangepaste objecten hebt gezien en RPC-oproepen en dergelijke hebt gemaakt, wil ik het hebben over een minder spannend onderwerp: foutafhandeling. Bij elke netwerktransactie kunnen er veel fouten optreden. De service start niet, er is een fout in de server, een object kan niet worden gevonden, klassen ontbreken en vele andere problemen. Tot nu toe heb ik gewoon de methode gebruikt fout.getString() om foutmeldingen te genereren. Maar deze methode is misschien niet altijd nuttig. Om het in actie te zien, verwijdert u het commentaar van de constructor CDCatalogus:

openbare CDCatalog() ( //catalogus = nieuwe hashtabel(); // Maak een map addCD(new CD("Nickel Creek", "Nickel Creek", "Sugar Hill")); addCD(nieuwe CD("Let it Fall", "Sean Watkins", "Sugar Hill")); addCD(nieuwe CD("Luchtgrenzen", "Michael Hedges", "Windham Hill")); addCD(nieuwe CD("Taproot", "Michael Hedges", "Windham Hill")); )

Compileer het opnieuw, start de servlet-engine opnieuw en host het opnieuw. Dit zal resulteren in een uitzondering NullPointerException wanneer de klassenconstructor CD probeert toe te voegen aan niet-geïnitialiseerd Hashtabel. Bij het starten van de client verschijnt een foutmelding, maar deze zal niet erg informatief zijn:

(gandalf)/javaxml2/build$ java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcrouter Bekijk de huidige cd-map. Fout: kan niet worden opgelost doelobject(Kan doelobject niet omzetten): null

Dit is helemaal niet de informatie die kan helpen bij het identificeren en corrigeren van een fout. Niettemin gaat het raamwerk goed om met foutafhandeling. Weet je nog DOMFaultListener, die u hebt opgegeven als de waarde van het element foutLuister? Voor hem is de tijd gekomen om aan het spel deel te nemen. Object geretourneerd in geval van een fout Schuld bevat DOM ( objectmodel document) org.w3c.dom.Element Met gedetailleerde informatie over de fout. Voeg eerst een importexpressie toe aan uw broncode java.util.Iterator:

java.net.URL importeren; importeer java.util.Enumeratie; java.util.Hashtable importeren; java.util.Iterator importeren; java.util.Vector importeren; importeer org.apache.soap.Constanten; importeer org.apache.soap.Fault; importeer org.apache.soap.SOAPException; importeer org.apache.soap.encoding.SOAPMappingRegistry; importeer org.apache.soap.encoding.soapenc.BeanSerializer; importeer org.apache.soap.rpc.Call; importeer org.apache.soap.rpc.Parameter; importeer org.apache.soap.rpc.Response; importeer org.apache.soap.util.xml.QName;

Laten we nu wijzigingen aanbrengen om fouten in te verwerken lijst methode():

if (!response.generatedFault()) ( Parameter returnValue = response.getReturnValue(); Hashtable catalog = (Hashtable)returnValue.getValue(); Opsomming e = catalog.keys(); while (e.hasMoreElements()) ( String title = (String)e.nextElement(); CD cd = (CD)catalog.get(titel); System.out.println(" "" + cd.getTitle() + "" artiest " + cd.getArtist() + " studios " + cd.getLabel()); else ( Foutfout = response.getFault(); System.out.println("Fout: " + fout.getFaultString()); Vectorgegevens = fout.getDetailEntries(); for (Iterator i = entry.iterator(); i.hasNext();) ( org.w3c.dom.Element entry = (org.w3c.dom.Element)i.next(); System.out.println(entry .getFirstChild().getNodeValue());

Methode gebruiken getDetailEntries() u krijgt toegang tot de SOAP-service en de onbewerkte dataserver die het probleem ondersteunt. De code verwerkt ze opnieuw (meestal is er maar één element, maar dit vereist veel aandacht) en onderschept de DOM Element, opgenomen in elke invoer. In wezen is dit de XML waarmee u werkt:

SOAP-ENV:Server.BadTargetObjectURI Kan doel niet oplossen: null Dit is wat wij willen!

Met andere woorden: het object Fout geeft u toegang tot het deel van de SOAP-envelop dat fouten bevat. Bovendien biedt Apache SOAP een Java-stacktrace wanneer er fouten optreden, waardoor de gedetailleerde informatie wordt verstrekt die nodig is om deze te corrigeren. Een element onderscheppen stapelTrace en het afdrukken van de knooppuntwaarde Tekst vanuit dit element kan uw client de serverstacktrace afdrukken. Door deze wijzigingen door te voeren en de client opnieuw op te starten, krijgt u het volgende resultaat:

C:\javaxml2\build>java javaxml2.CDLister http://localhost:8080/soap/servlet/rpcr outside Bekijk de huidige cd-map. Fout: Kan doel: null java.lang.NullPointerException in javaxml2.CDCatalog.addCD(CDCatalog.java:24) in javaxml2.CDCatalog niet omzetten. (CDCatalog.java:14) in java.lang.Class.newInstance0(Native Method) in java.lang.Class.newInstance(Class.java:237)

Het is iets beter, maar ten minste u kunt enkele weetjes zien dat er een uitzondering heeft plaatsgevonden NullPointerException en ontdek zelfs de regelnummers in de serverklassen waarin dit probleem zich voordeed. Het resultaat van deze recente wijzigingen heeft u een duidelijk beeld gegeven van het probleem met de foutafhandeling. Controleer nu uw serverklassen op fouten. Ja, ik was het bijna vergeten, vergeet daarvoor niet je klas terug te zetten CDCatalogus om de fouten te verwijderen die we opzettelijk hebben geïntroduceerd voor de duidelijkheid!

  1. Er wordt veel gesproken over het uitvoeren van SOAP via andere protocollen zoals SMTP (of zelfs Jabber). Doei SOAP-standaard biedt dit niet, maar soortgelijke functies kunnen in de toekomst worden toegevoegd. Wees daarom niet verbaasd als u actieve discussies over dit onderwerp tegenkomt.

Eenvoudig Object Access Protocol (SOAP) is een op XML gebaseerd protocol dat de regels definieert voor het verzenden van berichten via internet tussen verschillende applicatiesystemen. Het wordt voornamelijk gebruikt voor externe procedureaanroepen. SOAP is oorspronkelijk ontworpen om ‘boven’ HTTP te functioneren (om de integratie van SOAP in webapplicaties te vereenvoudigen), maar nu kunnen ook andere transportprotocollen, zoals SMTP, worden gebruikt.

Stel dat u een applicatietoegangsservice op internet maakt; Consumenten hebben interactie met deze dienst door deze van informatie te voorzien. Uw servers verwerken de gegevens en sturen de resultaten terug naar consumenten. Wat is de beste manier om de communicatie met het systeem te onderhouden?

U kunt een aangepaste client-server-applicatie maken en van consumenten eisen dat ze een speciale applicatie gebruiken cliënt programma. Maar als je serieus wilt gaan werken in de internetwereld, zul je een client moeten maken die op alle mogelijke clientplatforms draait: Windows, Macintosh, Unix, Linux, enz. Met andere woorden, je zult veel verschillende clients moeten schrijven .

Hoe zou jij je voelen? met behulp van internet? Deze oplossing is natuurlijk heel acceptabel, maar is nauw verbonden met de browserimplementatie, en ook hier zul je de infrastructuur moeten creëren om inkomende en uitgaande informatie te verzenden en ontvangen, en de gegevens voor een dergelijke uitwisseling moeten formatteren en verpakken. U kunt Java of ActiveX kiezen om complexe applicaties te implementeren, maar sommige gebruikers zullen uw diensten weigeren vanwege duidelijk te hoge bandbreedtevereisten en onvoldoende beveiliging.

Het enige dat nodig is, is een eenvoudig protocol dat het verpakken van applicatiegegevens vereenvoudigt en deze via het web verzendt met behulp van aan de inhoud aangepaste XML. Door dit te doen, zorgt het ervoor dat zowel de afzender als de ontvanger de inhoud van elk bericht gemakkelijk kunnen interpreteren. Tegelijkertijd zal het dankzij het gebruik van het HTTP-webprotocol als transportmiddel mogelijk zijn om de noodzaak om het niveau van firewallbescherming te verlagen te elimineren.

Het goed beschreven Simple Object Access Protocol (SOAP) is een eenvoudig ‘lijm’-protocol waarmee hosts op afstand applicatieobjecten kunnen aanroepen en resultaten kunnen retourneren. SOAP biedt een minimale set voorwaarden voor een applicatie om berichten door te geven: een client kan een bericht sturen om te kunnen bellen software-object en de server kan de resultaten van deze oproep retourneren.

SOAP is vrij eenvoudig: berichten zijn XML-documenten met SOAP-opdrachten. Hoewel SOAP theoretisch aan elk transportprotocol voor toepassingen kan worden gekoppeld, wordt het doorgaans in combinatie met HTTP gebruikt.

Kennard Scribner, een van de auteurs van het boek SOAP begrijpen: de gezaghebbende oplossing(Macmillan USA, 2000), zegt dat SOAP werkt door de informatie die nodig is om een ​​methode aan te roepen (zoals argumentwaarden en transactie-ID's) om te zetten in XML-formaat.

De gegevens worden ingekapseld in HTTP of een ander transportprotocol en verzonden naar de ontvanger, meestal de server. Deze server haalt de SOAP-gegevens uit het pakket, voert de vereiste verwerking uit en retourneert de resultaten als een SOAP-antwoord.

Scribner merkte op dat SOAP fungeert als een remote procedure call-protocol, vergelijkbaar met het Remote Method Invocation-protocol in Java of het General Inter-ORB Protocol in CORBA.

Omdat HTTP en XML vrijwel overal worden gebruikt, lijkt SOAP het meest schaalbare protocol voor externe procedureaanroepen dat tot nu toe is gebouwd, aldus Scribner. SOAP is niet ontworpen om te fungeren als een complete objectarchitectuur.

SOAP vervangt het Remote Method Invocation-protocol in Java, Distributed Component Object Model en CORBA niet; het biedt regels die elk van deze modellen kan gebruiken. SOAP is geen volledige oplossing. Het ondersteunt geen objectactivering of -beveiliging. Volgens Scribner "vertrouwen SOAP-ontwikkelaars erop dat gebruikers deze code zelf zullen toevoegen" door deze bovenop SOAP te bouwen, in plaats van deze onderdeel te maken van het protocol zelf.

De afbeelding toont een voorbeeld uit de SOAP 1.1-specificatie waarin een host een offerteservice aanvraagt ​​voor de prijs van een bepaald aandeel. Het SOAP-verzoek is ingebed in een HTTP POST en de verzoektekst specificeert het type verzoek en de parameter: het aandelensymbool. Het antwoord biedt ook een XML-object ingekapseld in het HTTP-antwoord met een enkele retourwaarde (in dit geval 34,5).

Kenmerken van SOAP

Met SOAP kunnen ontwikkelaars net zo snel webservices maken als ze SOAP-berichten kunnen schrijven om programma's voor bestaande applicaties op te roepen, en deze applicaties vervolgens aan eenvoudige webpagina's toevoegen. Maar daarnaast hebben ontwikkelaars de mogelijkheid om SOAP-oproepen in speciale applicaties te gebruiken en applicaties te creëren die naar de webpagina's van anderen kunnen worden geporteerd, waardoor het tijdrovende en dure ontwikkelingsproces wordt vermeden.

Volgens Mark Stiver, een andere auteur van het boek Understanding SOAP, is dit precies het doel dat Microsoft nastreeft met zijn veelbelovende .Net-platform. “Dit is waar SOAP uitblinkt. Het geeft ontwikkelaars een geweldige manier om applicaties te maken zonder zich zorgen te hoeven maken over mogelijke incompatibiliteit”, zegt hij.

SOAP-voorbeeld

Het volgende voorbeeld illustreert een SOAP-verzoek met de naam GetLastTradePrice, waarmee een klant een verzoek kan verzenden voor de nieuwste koersen voor een specifiek aandeel.

POST/StockQuote HTTP/1.1
Gastheer: stockquoteserver.com
Inhoudstype: tekst/xml; tekenset = "utf-8"
Inhoud lengte: nnnn
SOAPActie:"Sommige-URI"

De eerste vijf regels (onderdeel van de HTTP-header) specificeren het berichttype (POST), de host, het payload-type en de payload-lengte, en de SOAPAction-header specificeert het doel van het SOAP-verzoek. Het SOAP-bericht zelf is een XML-document met eerst een SOAP-envelop en vervolgens een XML-element dat de SOAP-naamruimte en eventuele attributen specificeert. Een SOAP-envelop kan een header bevatten (maar in dit geval niet), gevolgd door een SOAP-body. In ons voorbeeld bevat de hoofdtekst het GetLastTradePrice-verzoek en het symbool van het aandeel waarvoor de laatste koersen worden opgevraagd. Het antwoord op deze vraag zou er als volgt uit kunnen zien:

HTTP/1.1 200 OK
Inhoudstype: tekst/xml; tekenset = "utf-8"
Inhoud lengte: nnnn

Nogmaals, de eerste drie regels maken deel uit van de HTTP-header; Het SOAP-bericht zelf bestaat uit een envelop die het antwoord op het oorspronkelijke verzoek bevat, met de naam GetLastTradePriceResponse, en de geretourneerde waarde bevat, in ons geval 34.5.

Eenvoudig Object Access Protocol (SOAP) is een op XML gebaseerd protocol dat de regels definieert voor het verzenden van berichten via internet tussen verschillende applicatiesystemen. Het wordt voornamelijk gebruikt voor externe procedureaanroepen. SOAP is oorspronkelijk ontworpen om ‘boven’ HTTP te functioneren (om de integratie van SOAP in webapplicaties te vereenvoudigen), maar nu kunnen ook andere transportprotocollen, zoals SMTP, worden gebruikt.

Stel dat u een applicatietoegangsservice op internet maakt; Consumenten hebben interactie met deze dienst door deze van informatie te voorzien. Uw servers verwerken de gegevens en sturen de resultaten terug naar consumenten. Wat is de beste manier om de communicatie met het systeem te onderhouden?

U kunt een aangepaste client-servertoepassing maken en van consumenten eisen dat ze een aangepast clientprogramma gebruiken om toegang te krijgen tot uw service. Maar als je serieus wilt gaan werken in de internetwereld, zul je een client moeten maken die op alle mogelijke clientplatforms draait: Windows, Macintosh, Unix, Linux, enz. Met andere woorden, je zult veel verschillende clients moeten schrijven .

Wat vindt u van het gebruik van internet? Deze oplossing is natuurlijk heel acceptabel, maar is nauw verbonden met de browserimplementatie, en ook hier zul je de infrastructuur moeten creëren om inkomende en uitgaande informatie te verzenden en ontvangen, en de gegevens voor een dergelijke uitwisseling moeten formatteren en verpakken. U kunt Java of ActiveX kiezen om complexe applicaties te implementeren, maar sommige gebruikers zullen uw diensten weigeren vanwege duidelijk te hoge bandbreedtevereisten en onvoldoende beveiliging.

Het enige dat nodig is, is een eenvoudig protocol dat het verpakken van applicatiegegevens vereenvoudigt en deze via het web verzendt met behulp van aan de inhoud aangepaste XML. Door dit te doen, zorgt het ervoor dat zowel de afzender als de ontvanger de inhoud van elk bericht gemakkelijk kunnen interpreteren. Tegelijkertijd zal het dankzij het gebruik van het HTTP-webprotocol als transportmiddel mogelijk zijn om de noodzaak om het niveau van firewallbescherming te verlagen te elimineren.

Het goed beschreven Simple Object Access Protocol (SOAP) is een eenvoudig ‘lijm’-protocol waarmee hosts op afstand applicatieobjecten kunnen aanroepen en resultaten kunnen retourneren. SOAP biedt een minimale reeks voorwaarden voor een applicatie om berichten door te geven: een client kan een bericht verzenden om een ​​programmaobject aan te roepen, en de server kan de resultaten van die oproep retourneren.

SOAP is vrij eenvoudig: berichten zijn XML-documenten met SOAP-opdrachten. Hoewel SOAP theoretisch aan elk transportprotocol voor toepassingen kan worden gekoppeld, wordt het doorgaans in combinatie met HTTP gebruikt.

Kennard Scribner, een van de auteurs van het boek SOAP begrijpen: de gezaghebbende oplossing(Macmillan USA, 2000), zegt dat SOAP werkt door de informatie die nodig is om een ​​methode aan te roepen (zoals argumentwaarden en transactie-ID's) om te zetten in XML-formaat.

De gegevens worden ingekapseld in HTTP of een ander transportprotocol en verzonden naar de ontvanger, meestal de server. Deze server haalt de SOAP-gegevens uit het pakket, voert de vereiste verwerking uit en retourneert de resultaten als een SOAP-antwoord.

Scribner merkte op dat SOAP fungeert als een remote procedure call-protocol, vergelijkbaar met het Remote Method Invocation-protocol in Java of het General Inter-ORB Protocol in CORBA.

Omdat HTTP en XML vrijwel overal worden gebruikt, lijkt SOAP het meest schaalbare protocol voor externe procedureaanroepen dat tot nu toe is gebouwd, aldus Scribner. SOAP is niet ontworpen om te fungeren als een complete objectarchitectuur.

SOAP vervangt het Remote Method Invocation-protocol in Java, Distributed Component Object Model en CORBA niet; het biedt regels die elk van deze modellen kan gebruiken. SOAP is geen volledige oplossing. Het ondersteunt geen objectactivering of -beveiliging. Volgens Scribner "vertrouwen SOAP-ontwikkelaars erop dat gebruikers deze code zelf zullen toevoegen" door deze bovenop SOAP te bouwen, in plaats van deze onderdeel te maken van het protocol zelf.

De afbeelding toont een voorbeeld uit de SOAP 1.1-specificatie waarin een host een offerteservice aanvraagt ​​voor de prijs van een bepaald aandeel. Het SOAP-verzoek is ingebed in een HTTP POST en de verzoektekst specificeert het type verzoek en de parameter: het aandelensymbool. Het antwoord biedt ook een XML-object ingekapseld in het HTTP-antwoord met een enkele retourwaarde (in dit geval 34,5).

Kenmerken van SOAP

Met SOAP kunnen ontwikkelaars net zo snel webservices maken als ze SOAP-berichten kunnen schrijven om programma's voor bestaande applicaties op te roepen, en deze applicaties vervolgens aan eenvoudige webpagina's toevoegen. Maar daarnaast hebben ontwikkelaars de mogelijkheid om SOAP-oproepen in speciale applicaties te gebruiken en applicaties te creëren die naar de webpagina's van anderen kunnen worden geporteerd, waardoor het tijdrovende en dure ontwikkelingsproces wordt vermeden.

Volgens Mark Stiver, een andere auteur van het boek Understanding SOAP, is dit precies het doel dat Microsoft nastreeft met zijn veelbelovende .Net-platform. “Dit is waar SOAP uitblinkt. Het geeft ontwikkelaars een geweldige manier om applicaties te maken zonder zich zorgen te hoeven maken over mogelijke incompatibiliteit”, zegt hij.

SOAP-voorbeeld

Het volgende voorbeeld illustreert een SOAP-verzoek met de naam GetLastTradePrice, waarmee een klant een verzoek kan verzenden voor de nieuwste koersen voor een specifiek aandeel.

POST/StockQuote HTTP/1.1
Gastheer: stockquoteserver.com
Inhoudstype: tekst/xml; tekenset = "utf-8"
Inhoud lengte: nnnn
SOAPActie:"Sommige-URI"

De eerste vijf regels (onderdeel van de HTTP-header) specificeren het berichttype (POST), de host, het payload-type en de payload-lengte, en de SOAPAction-header specificeert het doel van het SOAP-verzoek. Het SOAP-bericht zelf is een XML-document met eerst een SOAP-envelop en vervolgens een XML-element dat de SOAP-naamruimte en eventuele attributen specificeert. Een SOAP-envelop kan een header bevatten (maar in dit geval niet), gevolgd door een SOAP-body. In ons voorbeeld bevat de hoofdtekst het GetLastTradePrice-verzoek en het symbool van het aandeel waarvoor de laatste koersen worden opgevraagd. Het antwoord op deze vraag zou er als volgt uit kunnen zien:

HTTP/1.1 200 OK
Inhoudstype: tekst/xml; tekenset = "utf-8"
Inhoud lengte: nnnn

Nogmaals, de eerste drie regels maken deel uit van de HTTP-header; Het SOAP-bericht zelf bestaat uit een envelop die het antwoord op het oorspronkelijke verzoek bevat, met de naam GetLastTradePriceResponse, en de geretourneerde waarde bevat, in ons geval 34.5.

hoeden 23 juli 2013 om 13:09 uur

Schrijven van een SOAP client-server applicatie in PHP

  • PHP
  • Handleiding

Dag Allemaal!
Het gebeurde zo dat ik onlangs webservices begon te ontwikkelen. Maar vandaag gaat het onderwerp niet over mij, maar over hoe we onze eigen XML-webservice kunnen schrijven op basis van het SOAP 1.2-protocol.

Ik hoop dat je na het lezen van dit onderwerp het volgende kunt:

  • schrijf uw eigen serverimplementatie van een webapplicatie;
  • schrijf uw eigen klantimplementatie van een webapplicatie;
  • schrijf uw eigen webservicebeschrijving (WSDL);
  • stuur de clientarrays met hetzelfde type gegevens naar de server.
Zoals je misschien al geraden hebt, wordt alle magie gedaan met behulp van PHP en de ingebouwde SoapClient- en SoapServer-klassen. Ons konijn zal een dienst zijn voor het verzenden van sms-berichten.

1 Probleemstelling

1.1 Grenzen

In het begin stel ik voor om het resultaat te behandelen dat we aan het einde van het onderwerp zullen bereiken. Zoals hierboven aangekondigd, gaan we een dienst schrijven voor het verzenden van sms-berichten, en meer precies, waar we berichten van zullen ontvangen verschillende bronnen via SOAP-protocol. Daarna zullen we bekijken in welke vorm ze naar de server komen. Het proces van het in de wachtrij plaatsen van berichten voor verdere verzending naar de provider valt helaas om vele redenen buiten het bestek van dit bericht.

1.2 Welke gegevens gaan we wijzigen?

Geweldig, we hebben de grenzen bepaald! De volgende stap die moet worden genomen, is beslissen welke gegevens we gaan uitwisselen tussen de server en de client. Over dit onderwerp raad ik aan om de haren niet te lang te splitsen en meteen de belangrijkste vragen voor jezelf te beantwoorden:
  • Welke gegevens moeten er minimaal naar de server worden verzonden om een ​​SMS-bericht naar een abonnee te kunnen sturen?
  • Welke gegevens moeten er minimaal vanaf de server worden verzonden om aan de behoeften van de klant te voldoen?
Iets zegt mij dat je hiervoor het volgende moet meesturen: In principe zijn deze twee kenmerken voldoende om te verzenden, maar ik stel me meteen het geval voor van een sms met verjaardagsgroeten die om 3 uur 's ochtends, of 4 uur, naar je toe komt! Op dit moment zal ik iedereen heel dankbaar zijn dat ze mij niet vergeten zijn! Daarom sturen we ook naar de server en
  • datum waarop het SMS-bericht is verzonden.
Het volgende dat ik naar de server wil sturen is:
  • Berichttype.
Deze parameter is niet verplicht, maar kan erg handig voor ons zijn als we de baas snel moeten vertellen hoeveel van onze klanten we "verrukt" hebben met ons nieuws, en ook een aantal mooie statistieken over deze kwestie willen opstellen.

En toch ben ik iets vergeten! Als we er wat meer over nadenken, is het de moeite waard om op te merken dat de client één sms-bericht of een aantal tegelijk naar de server kan sturen. Met andere woorden: één datapakket kan één tot oneindig veel berichten bevatten.

Hierdoor krijgen wij te horen dat we voor het versturen van een SMS bericht de volgende gegevens nodig hebben:

  • Mobiele telefoonnummer,
  • SMS-bericht tekst,
  • tijdstip waarop het sms-bericht naar de abonnee wordt verzonden,
  • berichttype.

We hebben de eerste vraag beantwoord, nu moeten we de tweede vraag beantwoorden. En misschien sta ik mezelf toe een beetje te rommelen. Daarom sturen we vanaf de server alleen Booleaanse gegevens, waarvan de betekenis de volgende betekenis heeft:

  • WAAR – het pakket heeft de server bereikt, heeft de authenticatie doorstaan ​​en is in de wachtrij geplaatst voor verzending naar de SMS-provider
  • FALSE – in alle andere gevallen

Hiermee is de beschrijving van de probleemstelling afgerond! En tot slot, laten we naar het leuke gedeelte gaan: laten we uitzoeken wat voor soort vreemd beest deze SOAP is!

2 Wat is zeep?

Over het algemeen was ik aanvankelijk niet van plan iets te schrijven over wat SOAP is en wilde ik mezelf beperken tot links naar de w3.org-website met de nodige specificaties, evenals links naar Wikipedia. Maar helemaal aan het einde besloot ik een korte opmerking over dit protocol te schrijven.

En ik zal mijn verhaal beginnen met het feit dat dit gegevensuitwisselingsprotocol behoort tot een subset van protocollen gebaseerd op het zogenaamde RPC-paradigma (Remote Procedure Call), waarvan de tegenpool REST (Representational State Transfer) is. Je kunt hier meer over lezen op Wikipedia; links naar artikelen staan ​​helemaal aan het einde van het onderwerp. Uit deze artikelen moeten we het volgende begrijpen: “De RPC-aanpak maakt het gebruik van een klein aantal mogelijk netwerkbronnen Met grote hoeveelheid methoden en complexe protocollen. Met de REST-aanpak zijn het aantal methoden en de protocolcomplexiteit strikt beperkt, wat betekent dat het aantal individuele bronnen groot kan zijn.” Dat wil zeggen, voor ons betekent dit dat er bij de RPC-aanpak op de site altijd één input (link) naar de dienst zal zijn en welke procedure we moeten aanroepen om de inkomende gegevens te verwerken die we samen met de gegevens overdragen, terwijl met de REST-aanpak in onze De site heeft veel inputs (links), die elk slechts bepaalde gegevens accepteren en verwerken. Als iemand die leest het verschil in deze benaderingen nog eenvoudiger kan uitleggen, schrijf dan in de reacties!

Het volgende dat we moeten weten over SOAP is dat dit protocol dezelfde XML gebruikt als een transport, wat enerzijds erg goed is, omdat onmiddellijk krijgt ons arsenaal de volledige kracht van een stapel technologieën die erop zijn gebaseerd gegeven taal markup, namelijk XML-Schema - een taal voor het beschrijven van de structuur van een XML-document (bedankt Wikipedia!), die automatische validatie mogelijk maakt van gegevens die door de server van clients worden ontvangen.

En nu weten we dus dat SOAP een protocol is dat wordt gebruikt om externe procedureaanroepen te implementeren en dat het XML als transportmiddel gebruikt! Als je het artikel op Wikipedia leest, kun je daar ook van leren dat het via elk protocol op applicatieniveau kan worden gebruikt, en niet alleen in combinatie met HTTP (helaas beschouwen we in dit onderwerp alleen SOAP via HTTP). En weet je wat ik het leukste vind aan dit alles? Als er geen gissingen zijn, dan geef ik een hint - SOAP!... Nog steeds geen gissingen?... Weet je zeker dat je het artikel op Wikipedia hebt gelezen?... Over het algemeen zal ik je niet verder martelen. Daarom ga ik meteen naar het antwoord: “SOAP (van het Engelse Simple Object Access Protocol - eenvoudig protocol toegang tot objecten; tot specificatie 1.2)". Het meest opmerkelijke aan deze regel staat cursief! Ik weet niet welke conclusies je uit dit alles hebt getrokken, maar ik zie het volgende - aangezien dit protocol op geen enkele manier "eenvoudig" kan worden genoemd (en blijkbaar is zelfs w3 het hiermee eens), werd het vanaf versie 1.2 op de een of andere manier niet meer gedecodeerd ! En het werd bekend als SOAP, gewoon SOAP, punt uit.

Nou, oké, excuseer me, ik ben een beetje op een zijspoor geraakt. Zoals ik eerder schreef, wordt XML gebruikt als transportmiddel, en de pakketten die tussen de client en de server reizen worden SOAP-enveloppen genoemd. Als u de algemene structuur van de envelop in ogenschouw neemt, zal deze u heel bekend voorkomen, omdat... lijkt op de structuur van een HTML-pagina. Het heeft een hoofdgedeelte - Omhullen, inclusief secties Koptekst En Lichaam, of Schuld. IN Lichaam gegevens worden verzonden en het is een verplicht onderdeel van de envelop Koptekst is optioneel. IN Koptekst autorisatie of andere gegevens die niet direct verband houden met de invoergegevens van de webserviceprocedures kunnen worden verzonden. Over Schuld er is niets bijzonders te vertellen, behalve dat het bij eventuele fouten vanaf de server naar de client komt.

Dit is waar mijn recensieverhaal over het SOAP-protocol eindigt (we zullen de enveloppen zelf en hun structuur in meer detail bekijken wanneer onze client en server eindelijk leren om ze op elkaar uit te voeren) en een nieuw begint - over de SOAP-metgezel genaamd WSDL(Beschrijvingstaal voor webservices). Ja, ja, dit is precies wat de meesten van ons bang maakt om zelfs maar te proberen onze API op dit protocol te implementeren. Als gevolg hiervan vinden we meestal ons wiel opnieuw uit met JSON als transportmiddel. Dus wat is WSDL? WSDL is een taal voor het beschrijven en benaderen van webservices, gebaseerd op de XML-taal (c) Wikipedia. Als deze definitie je niet de hele heilige betekenis van deze technologie duidelijk maakt, dan zal ik proberen het in mijn eigen woorden te beschrijven!

WSDL is ontworpen om onze klanten normaal met de server te laten communiceren. Om dit te doen, beschrijft het bestand met de extensie “*.wsdl” de volgende informatie:

  • Welke naamruimten zijn gebruikt?
  • Welke dataschema's zijn gebruikt?
  • Welke soorten berichten verwacht de webservice van klanten?
  • Welke gegevens horen bij welke webserviceprocedures,
  • Welke procedures bevat de webservice?
  • Hoe moet de klant de webserviceprocedures aanroepen,
  • Naar welk adres moeten klantoproepen worden verzonden?
Als gezien, dit bestand en er is de hele webservice. Door het adres van het WSDL-bestand in de client op te geven, weten we alles over elke webservice! Hierdoor hoeven we helemaal niets te weten over waar de webdienst zelf zich bevindt. Het enige dat u hoeft te weten, is de locatie van het WSDL-bestand! We zullen er snel achter komen dat SOAP niet zo eng is als Russische spreekwoorden beweren.

3 Inleiding tot XML-Schema

Nu weten we veel over wat SOAP is, wat erin zit, en hebben we een overzicht van de technologiestapel eromheen. Omdat SOAP in de eerste plaats een manier van interactie is tussen een client en een server, en XML-opmaaktaal als transportmiddel daarvoor wordt gebruikt, deze sectie We zullen even bekijken hoe automatische gegevensvalidatie plaatsvindt met behulp van XML-schema's.

De belangrijkste taak van het diagram is het beschrijven van de structuur van de gegevens die we gaan verwerken. Alle gegevens in XML-schema's zijn onderverdeeld in eenvoudig(scalair) en complex(structuren) soorten. Eenvoudige typen omvatten de volgende typen:

  • lijn,
  • nummer,
  • Booleaanse waarde,
  • datum van.
Iets heel eenvoudigs zonder extensies erin. Hun tegenpool zijn complexe complexe typen. Het eenvoudigste voorbeeld van een complex type dat bij iedereen opkomt zijn objecten. Bijvoorbeeld een boek. Het boek bestaat uit eigenschappen: auteur, Naam, prijs, ISBN-nummer enz. En deze eigenschappen kunnen op hun beurt zowel eenvoudige als complexe typen zijn. En de taak van het XML-schema is om dit te beschrijven.

Ik stel voor om niet ver te gaan en een XML-schema te schrijven voor ons sms-bericht! Hieronder vindt u de xml-beschrijving van het sms-bericht:

71239876543 Test bericht 20-07-2013T12:00:00 12
Ons complexe typediagram ziet er als volgt uit:


Dit bericht luidt als volgt: We hebben een variabele " bericht"type" Bericht" en er is een complex type genaamd " Bericht", die bestaat uit een opeenvolgende reeks elementen " telefoon" typ snaar, « tekst" typ snaar, « datum" typ datum Tijd, « type" typ decimale. Deze typen zijn eenvoudig en zijn al gedefinieerd in de schemabeschrijving. Gefeliciteerd! We hebben zojuist ons eerste XML-schema geschreven!

Ik denk dat de betekenis van de elementen " element" En " complexType"Alles is je min of meer duidelijk geworden, dus we concentreren ons er niet meer op en laten we meteen overgaan naar het componist-element" reeks" Wanneer we het componistelement gebruiken " reeks“We informeren u dat de elementen die erin zijn opgenomen altijd in de volgorde moeten worden geplaatst die in het diagram is aangegeven, en dat ze allemaal verplicht zijn. Maar wanhoop niet! Er zijn nog twee componistelementen in XML-schema's: " keuze" En " alle" Componist " keuze" kondigt aan dat er een van de elementen erin moet staan, en de componist " alle» – elke combinatie van de genoemde elementen.

Zoals u zich herinnert, zijn we in het eerste deel van het onderwerp overeengekomen dat sms-berichten van één tot oneindig in een pakket kunnen worden verzonden. Daarom stel ik voor om te begrijpen hoe dergelijke gegevens in het XML-schema worden gedeclareerd. De algemene pakketstructuur kan er als volgt uitzien:

71239876543 Testbericht 1 20-07-2013T12:00:00 12 71239876543 Testbericht N 20-07-2013T12:00:00 12
Het diagram voor zo'n complex type ziet er als volgt uit:


Het eerste blok bevat de bekende declaratie van het complexe type “ Bericht" Als je het gemerkt hebt, dan in elke eenvoudig soort, inbegrepen " Bericht", er zijn nieuwe verduidelijkende attributen toegevoegd " minKomt voor" En " maxKomt voor" Zoals je uit de naam zou kunnen raden, is de eerste ( minKomt voor) geeft aan dat deze reeks minstens één element van het type “ telefoon», « tekst», « datum" En " type", terwijl de volgende ( maxKomt voor) attribuut verklaart ons dat er hoogstens één zo'n element in onze reeks aanwezig is. Als gevolg hiervan krijgen we, wanneer we onze eigen schema's voor welke gegevens dan ook schrijven, de grootste keuze in hoe we deze moeten configureren!

Het tweede blok van het diagram declareert het element " berichtLijst"type" BerichtenLijst" Het is duidelijk dat " BerichtenLijst" is een complex type dat minstens één element bevat " bericht", maar het maximale aantal van dergelijke elementen is niet beperkt!

4 Schrijf uw WSDL

Weet u nog dat WSDL onze webservice is? Ik hoop dat je het je herinnert! Terwijl we het schrijven, draait onze kleine webservice erop. Daarom raad ik aan om er niet mee te rommelen.

Om alles correct voor ons te laten werken, moeten we over het algemeen een WSDL-bestand met het juiste MIME-type naar de client overbrengen. Om dit te doen, moet u uw webserver dienovereenkomstig configureren, namelijk het MIME-type voor bestanden met de extensie “*.wsdl” instellen op de volgende regel:

Applicatie/wsdl+xml
Maar in de praktijk stuurde ik de HTTP-header meestal via PHP " tekst/xml»:

Header("Inhoudstype: tekst/xml; charset=utf-8");
en alles werkte prima!

Ik wil je meteen waarschuwen dat onze eenvoudige webservice een nogal indrukwekkende beschrijving zal hebben, dus wees niet ongerust, want... Het grootste deel van de tekst is verplicht water en als je het eenmaal hebt geschreven, kun je het voortdurend van de ene webservice naar de andere kopiëren!

Omdat WSDL XML is, moet u hierover direct in de allereerste regel schrijven. Het hoofdelement van het bestand moet altijd de naam " definities»:


Normaal gesproken bestaat WSDL uit 4-5 hoofdblokken. Het allereerste blok is de definitie van een webservice of, met andere woorden, het toegangspunt.


Hier staat dat we een dienst hebben genaamd - “ Sms-service" In principe kunnen alle namen in het WSDL-bestand door u worden gewijzigd in wat u maar wilt, omdat ze spelen absoluut geen rol.

Hierna maken wij dat bekend in onze webservice" Sms-service" er is een toegangspunt ("poort") genaamd " SmsServicePort" Naar dit toegangspunt worden alle verzoeken van clients naar de server verzonden. En geef in het element “ adres» link naar het handlerbestand dat verzoeken accepteert.

Nadat we de webservice hebben gedefinieerd en het toegangspunt ervoor hebben gespecificeerd, moeten we er ondersteunde procedures aan koppelen:


Om dit te doen, wordt vermeld welke bewerkingen en in welke vorm ze zullen worden aangeroepen. Die. voor poort " SmsServicePort"een binding genaamd" is gedefinieerd SmsServiceBinding", die een oproeptype heeft " rpc"en HTTP wordt gebruikt als transmissieprotocol. We hebben hier dus aangegeven dat we een RPC-aanroep via HTTP zullen doen. Hierna beschrijven we welke procedures ( operatie) worden ondersteund in de webservice. Wij zullen slechts één procedure steunen – “ verstuur sms" Via deze procedure worden onze prachtige berichten naar de server verzonden! Nadat de procedure is aangegeven, is het noodzakelijk om aan te geven in welke vorm de gegevens zullen worden verzonden. In dit geval wordt aangegeven dat standaard SOAP-enveloppen zullen worden gebruikt.

Daarna moeten we de procedure aan berichten binden:


Om dit te doen, specificeren we dat onze binding van het type is " SmsServicePortType"en in het element" poortType"met de naam van hetzelfde type geven we de binding van procedures aan berichten aan. En dus zal het binnenkomende bericht (van client naar server) “ stuurSmsVerzoek", en uitgaand (van server naar client) " stuurSmsantwoord" Zoals alle namen in WSDL zijn de namen van inkomende en uitgaande berichten willekeurig.

Nu moeten we de berichten zelf beschrijven, d.w.z. inkomend en uitgaand:


Om dit te doen voegen we de elementen toe " bericht"met namen" stuurSmsVerzoek" En " stuurSmsantwoord"respectievelijk. Daarin geven we aan dat de invoer een envelop moet zijn waarvan de structuur overeenkomt met het gegevenstype " Verzoek" Waarna een envelop wordt geretourneerd van de server met daarin het gegevenstype - “ Antwoord».

Nu moeten we nog een klein stukje doen: een beschrijving van deze typen toevoegen aan ons WSDL-bestand! En hoe denkt u dat de WSDL inkomende en uitgaande gegevens beschrijft? Ik denk dat je alles al lang geleden hebt begrepen en tegen jezelf hebt gezegd dat je XML-schema's gebruikt! En je zult volkomen gelijk hebben!


Je kunt ons feliciteren! Onze eerste WSDL is geschreven! En we zijn een stap dichter bij het bereiken van ons doel.
Vervolgens bekijken we wat PHP ons biedt voor het ontwikkelen van onze eigen gedistribueerde applicaties.

5 Onze eerste SOAP-server

Eerder schreef ik dat we voor het maken van een SOAP-server in PHP de ingebouwde SoapServer-klasse zullen gebruiken. Om alles in orde te maken verdere acties gebeurde op dezelfde manier als de mijne, je zult je PHP een beetje moeten aanpassen. Om nog preciezer te zijn, moet u ervoor zorgen dat de extensie “php-soap” is geïnstalleerd. Hoe u het op uw webserver installeert, leest u het beste op de officiële PHP-website (zie de lijst met referenties).

Nadat alles is geïnstalleerd en geconfigureerd, moeten we een bestand aanmaken in de hoofdmap van uw hosting “ smsservice.php» met de volgende inhoud:

setClass("SoapSmsGateWay"); //Start de server $server->handle();
Ik hoop dat het niet nodig is om uit te leggen wat er boven de lijn staat met de functie "ini_set". Omdat daar wordt bepaald welke HTTP-headers we van de server naar de client gaan sturen en wordt de omgeving geconfigureerd. In lijn met “ini_set” schakelen we caching van het WSDL-bestand uit, zodat onze wijzigingen daarin onmiddellijk van kracht worden op de client.

Nu komen we bij de server! Zoals u kunt zien, neemt de gehele SOAP-server slechts drie regels in beslag! Op de eerste regel maken we een nieuw exemplaar van het SoapServer-object en geven het adres van onze WSDL-beschrijving van de webservice door aan de constructor ervan. Nu weten we dat het zich in de root van de hosting zal bevinden in een bestand met de voor zichzelf sprekende naam “ smsservice.wsdl.php" In de tweede regel vertellen we de SOAP-server welke klasse moet worden opgehaald om de van de client ontvangen envelop te verwerken en de envelop met het antwoord terug te sturen. Zoals je misschien al geraden hebt, zal in deze klasse onze enige methode worden beschreven verstuur sms. Op de derde regel starten we de server! Dat is alles, onze server is klaar! Waarmee ik ons ​​allemaal feliciteer!

Nu moeten we het WSDL-bestand maken. Om dit te doen, kun je eenvoudig de inhoud uit de vorige sectie kopiëren, of je vrijheden permitteren en er een beetje een “sjabloon” van maken:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" naam="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
In dit stadium zouden we volledig tevreden moeten zijn met de resulterende server, omdat Wij kunnen de binnenkomende enveloppen loggen en vervolgens rustig de binnenkomende gegevens analyseren. Om iets op de server te kunnen ontvangen, hebben we een client nodig. Dus laten we aan de slag gaan!

6 SOAP-client onderweg

Allereerst moeten we een bestand maken waarin we de client zullen schrijven. Zoals gewoonlijk zullen we het in de root van de host maken en het " noemen klant.php", en binnenin zullen we het volgende schrijven:

messageList = nieuwe Berichtenlijst(); $req->messageList->bericht = nieuw bericht(); $req->messageList->bericht->telefoon = "79871234567"; $req->messageList->message->text = "Testbericht 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->bericht->type = 15; $client = nieuwe SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
Laten we onze objecten beschrijven. Toen we de WSDL schreven, werden er drie entiteiten beschreven voor de envelop die binnenkwam op de server: Verzoek, BerichtenLijst En Bericht. Dienovereenkomstig klassen Verzoek, BerichtenLijst En Bericht zijn weerspiegelingen van deze entiteiten in ons PHP-script.

Nadat we de objecten hebben gedefinieerd, moeten we een object maken ( $vereist), die we naar de server sturen. Daarna komen de twee meest gekoesterde regels voor ons! Onze SOAP-klant! Geloof het of niet, dit is genoeg voor onze server om berichten van de client te ontvangen, maar ook voor onze server om deze met succes te ontvangen en te verwerken! In de eerste daarvan maken we een exemplaar van de klasse SoapClient en geven we het adres van de locatie van het WSDL-bestand door aan de constructor ervan, en in de parameters geven we expliciet aan dat we zullen werken met het SOAP-protocol versie 1.2. Op de volgende regel noemen we de methode verstuur sms voorwerp $klant en geef het resultaat onmiddellijk weer in de browser.
Laten we het uitvoeren en zien wat we uiteindelijk hebben gekregen!

Het volgende object is vanaf de server naar mij teruggestuurd:

Object(stdClass) public "status" => boolean waar
En dat is geweldig, want... Nu weten we zeker dat onze server werkt en niet alleen werkt, maar ook enkele waarden kan teruggeven aan de client!

Laten we nu eens kijken naar het logboek dat we voorzichtig aan de serverzijde bijhouden! In het eerste deel zien we de onbewerkte gegevens die op de server zijn aangekomen:

79871234567 Testbericht 1 21-07-2013T15:00:00.26 15
Dit is de envelop. Nu weet je hoe het eruit ziet! Maar het is onwaarschijnlijk dat we er de hele tijd naar willen kijken, dus laten we het object uit het logbestand deserialiseren en kijken of alles in orde is:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 1 " (lengte=37) public "date" => string "2013-07-21T15:00:00.26" (lengte=22) public "type" => string "15" (lengte=2)
Zoals u kunt zien, is het object correct gedeserialiseerd, waarvoor ik ons ​​allemaal wil feliciteren! Er wacht ons nog iets interessants! We sturen de client namelijk niet slechts één sms-bericht naar de server, maar een heel pakket (om preciezer te zijn: drie)!

7 Complexe objecten verzenden

Laten we eens nadenken over hoe we een hele reeks berichten in één pakket naar de server kunnen overbrengen? Waarschijnlijk het meest op een eenvoudige manier er zal een array-organisatie zijn binnen het messageList-element! Laten we dit doen:

// maak een object om naar de server te sturen $req = new Request(); $req->messageList = nieuwe Berichtenlijst(); $msg1 = nieuw bericht(); $msg1->telefoon = "79871234567"; $msg1->text = "Testbericht 1"; $msg1->datum = "21-07-2013T15:00:00.26"; $msg1->type = 15; $msg2 = nieuw bericht(); $msg2->telefoon = "79871234567"; $msg2->text = "Testbericht 2"; $msg2->datum = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = nieuw bericht(); $msg3->telefoon = "79871234567"; $msg3->text = "Testbericht 3"; $msg3->datum = "22-08-2014T16:01:10"; $msg3->type = 17; $req->messageList->bericht = $msg1; $req->messageList->bericht = $msg2; $req->messageList->bericht = $msg3;
Uit onze logbestanden blijkt dat het volgende pakket van de client is ontvangen:

79871234567 Testbericht 1 21-07-2013T15:00:00.26 15 79871234567 Testbericht 2 22-08-2014T16:01:10 16 79871234567 Testbericht 3 22-08-2014T16:01:10 17
Wat een onzin, zegt u? En in zekere zin heb je gelijk, want... Zodra we hoorden dat een object de client verliet, kwam het in absoluut dezelfde vorm naar onze server in de vorm van een envelop. Toegegeven, sms-berichten werden niet in XML geserialiseerd op de manier die wij nodig hadden: ze moesten in elementen worden verpakt bericht, niet in Structuur. Laten we nu eens kijken in welke vorm zo'n object in de methode terechtkomt verstuur sms:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 1" (lengte=37) public "date" => string "2013-07-21T15:00:00.26" (lengte=22) public " type" => string "15" (lengte=2) 1 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 2" (lengte= 37) public "date" => string "2014-08-22T16:01:10" (lengte=19) public "type" => string "16" (lengte=2) 2 => object(stdClass) public "phone " => string "79871234567" (lengte=11) public "text" => string "Testbericht 3" (lengte=37) public "date" => string "2014-08-22T16:01:10" (lengte= 19) openbaar "type" => tekenreeks "17" (lengte=2)
Wat levert deze kennis ons op? Alleen dat het pad dat we hebben gekozen niet correct is en we geen antwoord hebben gekregen op de vraag: “Hoe kunnen we op de server komen juiste structuur gegevens? Maar ik stel voor om niet te wanhopen en te proberen onze array naar het type te converteren een voorwerp:

$req->messageList->bericht = (object)$req->messageList->bericht;
In dit geval ontvangen wij nog een envelop:

79871234567 Testbericht 1 21-07-2013T15:00:00.26 15 79871234567 Testbericht 2 22-08-2014T16:01:10 16 79871234567 Testbericht 3 22-08-2014T16:01:10 17
Kwam in de methode verstuur sms het object heeft de volgende structuur:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 1" (lengte=37) public "date" => string "2013-07-21T15:00:00.26" (lengte=22) public " type" => string "15" (lengte=2) 1 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 2" (lengte= 37) public "date" => string "2014-08-22T16:01:10" (lengte=19) public "type" => string "16" (lengte=2) 2 => object(stdClass) public "phone " => string "79871234567" (lengte=11) public "text" => string "Testbericht 3" (lengte=37) public "date" => string "2014-08-22T16:01:10" (lengte= 19) openbaar "type" => tekenreeks "17" (lengte=2)
Wat mij betreft: “de som verandert niet als de plaatsen van de termen worden gewijzigd” (c). Wat BOGUS, Wat Structuur– we hebben ons doel nog niet bereikt! En om dit te bereiken, moeten we ervoor zorgen dat in plaats van deze onbegrijpelijke namen onze inheemse naam wordt weergegeven bericht. Maar de auteur weet nog niet hoe hij dit moet bereiken. Het enige wat we dus kunnen doen is de extra container weggooien. Met andere woorden, we zullen er nu voor zorgen dat in plaats van bericht werd BOGUS! Om dit te doen, wijzigt u het object als volgt:

// maak een object om naar de server te sturen $req = new Request(); $msg1 = nieuw bericht(); $msg1->telefoon = "79871234567"; $msg1->text = "Testbericht 1"; $msg1->datum = "21-07-2013T15:00:00.26"; $msg1->type = 15; $msg2 = nieuw bericht(); $msg2->telefoon = "79871234567"; $msg2->text = "Testbericht 2"; $msg2->datum = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = nieuw bericht(); $msg3->telefoon = "79871234567"; $msg3->text = "Testbericht 3"; $msg3->datum = "22-08-2014T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
Wat als we geluk hebben en de juiste naam uit het diagram komt? Laten we hiervoor eens kijken naar de envelop die is aangekomen:

79871234567 Testbericht 1 21-07-2013T15:00:00.26 15 79871234567 Testbericht 2 22-08-2014T16:01:10 16 79871234567 Testbericht 3 22-08-2014T16:01:10 17
Ja, er is geen wonder gebeurd! BOGUS– wij zullen niet winnen! Kwam naar verstuur sms het object ziet er in dit geval als volgt uit:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (grootte=3) 0 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public " text" => string "Testbericht 1" (lengte=37) public "date" => string "2013-07-21T15:00:00.26" (lengte=22) public "type" => string "15" (lengte =2) 1 => object(stdClass) public "phone" => string "79871234567" (lengte=11) public "text" => string "Testbericht 2" (lengte=37) public "date" => string " 2014-08-22T16:01:10" (lengte=19) public "type" => string "16" (lengte=2) 2 => object(stdClass) public "phone" => string "79871234567" (lengte= 11) public "text" => string "Testbericht 3" (lengte=37) public "date" => string "2014-08-22T16:01:10" (lengte=19) public "type" => string " 17" (lengte=2)
Zoals ze zeggen: “Bijna”! Op dit (enigszins trieste) punt stel ik voor om de zaken langzaam af te ronden en enkele conclusies voor onszelf te trekken.

8 Conclusie

Eindelijk zijn we hier aangekomen! Laten we eens kijken wat u nu kunt doen:
  • u kunt het WSDL-bestand schrijven dat nodig is voor uw webservice;
  • u kunt eenvoudig uw eigen client schrijven die via SOAP met de server kan communiceren;
  • je kunt je eigen schrijven eigen server communiceren met de buitenwereld via SOAP;
  • u kunt vanaf uw client arrays van hetzelfde type objecten naar de server sturen (met enkele beperkingen).
We hebben ook enkele ontdekkingen gedaan tijdens ons kleine onderzoek:
  • de native SoapClient-klasse serialiseert gegevensstructuren van hetzelfde type in XML niet correct;
  • bij het serialiseren van een array naar XML creëert het een extra element genaamd Structuur;
  • bij het serialiseren van een object naar XML wordt een extra element gemaakt met de naam BOGUS;
  • BOGUS minder kwaad dan Structuur vanwege het feit dat de envelop compacter is (er worden geen extra naamruimten toegevoegd aan de XML-header van de envelop);
  • Helaas valideert de klasse SoapServer de envelopgegevens niet automatisch met ons XML-schema (misschien doen andere servers dit ook niet).